Fix datetime issues.

This commit is contained in:
Buster Neece 2023-01-06 12:39:51 -06:00
parent 4ceb167f5e
commit 10c8069719
No known key found for this signature in database
GPG Key ID: F1D2E64A0005E80E
4 changed files with 223 additions and 215 deletions

View File

@ -20,9 +20,6 @@
:fields="fields" :fields="fields"
:api-url="apiUrl" :api-url="apiUrl"
> >
<template #cell(date_time)="row">
{{ formatTimestamp(row.item.timestamp) }}
</template>
<template #cell(operation)="row"> <template #cell(operation)="row">
<span <span
v-if="row.item.operation_text === 'insert'" v-if="row.item.operation_text === 'insert'"
@ -135,9 +132,21 @@ const dateRange = ref({
}); });
const {$gettext} = useTranslate(); const {$gettext} = useTranslate();
const {timeConfig} = useAzuraCast();
const fields = [ const fields = [
{key: 'date_time', label: $gettext('Date/Time'), sortable: false}, {
key: 'timestamp',
label: $gettext('Date/Time'),
sortable: false,
formatter: (value) => {
return DateTime.fromSeconds(value).toLocaleString(
{
...DateTime.DATETIME_SHORT, ...timeConfig
}
);
}
},
{key: 'user', label: $gettext('User'), sortable: false}, {key: 'user', label: $gettext('User'), sortable: false},
{key: 'operation', isRowHeader: true, label: $gettext('Operation'), sortable: false}, {key: 'operation', isRowHeader: true, label: $gettext('Operation'), sortable: false},
{key: 'identifier', label: $gettext('Identifier'), sortable: false}, {key: 'identifier', label: $gettext('Identifier'), sortable: false},
@ -160,16 +169,6 @@ const $dataTable = ref(); // DataTable Template Ref
const relist = () => { const relist = () => {
$dataTable.value.relist(); $dataTable.value.relist();
}; };
const formatTimestamp = (unix_timestamp) => {
const {timeConfig} = useAzuraCast();
return DateTime.fromSeconds(unix_timestamp).toLocaleString(
{
...DateTime.DATETIME_SHORT, ...timeConfig
}
);
}
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@ -5,7 +5,7 @@
<h2 class="card-title flex-fill my-0"> <h2 class="card-title flex-fill my-0">
{{ $gettext('Song Playback Timeline') }} {{ $gettext('Song Playback Timeline') }}
</h2> </h2>
<div class="flex-shrink"> <div class="flex-shrink buttons">
<a <a
id="btn-export" id="btn-export"
class="btn btn-bg" class="btn btn-bg"
@ -26,22 +26,13 @@
</div> </div>
</div> </div>
<data-table <data-table
ref="datatable" ref="$datatable"
responsive responsive
paginated paginated
select-fields select-fields
:fields="fields" :fields="fields"
:api-url="apiUrl" :api-url="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>
<template #cell(delta)="row"> <template #cell(delta)="row">
<span class="typography-subheading"> <span class="typography-subheading">
<template v-if="row.item.delta_total > 0"> <template v-if="row.item.delta_total > 0">
@ -92,116 +83,121 @@
</div> </div>
</template> </template>
<script> <script setup>
import Icon from "~/components/Common/Icon"; import Icon from "~/components/Common/Icon";
import DataTable from "~/components/Common/DataTable"; import DataTable from "~/components/Common/DataTable";
import DateRangeDropdown from "~/components/Common/DateRangeDropdown"; import DateRangeDropdown from "~/components/Common/DateRangeDropdown";
import {DateTime} from 'luxon'; import {DateTime} from 'luxon';
import {useAzuraCast} from "~/vendor/azuracast"; import {useAzuraCast} from "~/vendor/azuracast";
import {computed, ref} from "vue";
import {useTranslate} from "~/vendor/gettext";
export default { const props = defineProps({
name: 'StationsReportsTimeline', baseApiUrl: {
components: {DateRangeDropdown, DataTable, Icon}, type: String,
props: { required: true
baseApiUrl: {
type: String,
required: true
},
stationTimeZone: {
type: String,
required: true
}
}, },
data() { stationTimeZone: {
let nowTz = DateTime.now().setZone(this.stationTimeZone); type: String,
required: true
return {
dateRange: {
startDate: nowTz.minus({days: 13}).toJSDate(),
endDate: nowTz.toJSDate(),
},
fields: [
{
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
}
],
}
},
computed: {
apiUrl() {
let apiUrl = new URL(this.baseApiUrl, document.location);
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();
},
exportUrl() {
let exportUrl = new URL(this.apiUrl, document.location);
let exportUrlParams = exportUrl.searchParams;
exportUrlParams.set('format', 'csv');
return exportUrl.toString();
},
},
methods: {
relist() {
this.$refs.datatable.relist();
},
abs(val) {
return Math.abs(val);
},
formatTimestamp(unix_timestamp) {
const {timeConfig} = useAzuraCast();
return DateTime.fromSeconds(unix_timestamp).toLocaleString(
{...DateTime.DATETIME_SHORT, ...timeConfig}
);
},
formatTimestampStation(unix_timestamp) {
const {timeConfig} = useAzuraCast();
return DateTime.fromSeconds(unix_timestamp).setZone(this.stationTimeZone).toLocaleString(
{...DateTime.DATETIME_SHORT, ...timeConfig}
);
}
} }
});
const nowTz = DateTime.now().setZone(props.stationTimeZone);
const dateRange = ref(
{
startDate: nowTz.minus({days: 13}).toJSDate(),
endDate: nowTz.toJSDate(),
}
);
const {$gettext} = useTranslate();
const {timeConfig} = useAzuraCast();
const fields = [
{
key: 'played_at',
label: $gettext('Date/Time (Browser)'),
selectable: true,
sortable: false,
formatter: (value) => {
return DateTime.fromSeconds(
value,
{zone: 'system'}
).toLocaleString(
{...DateTime.DATETIME_SHORT, ...timeConfig}
);
}
},
{
key: 'played_at_station',
label: $gettext('Date/Time (Station)'),
sortable: false,
selectable: true,
visible: false,
formatter: (value, key, item) => {
return DateTime.fromSeconds(
item.played_at,
{zone: props.stationTimeZone}
).toLocaleString(
{...DateTime.DATETIME_SHORT, ...timeConfig}
);
}
},
{
key: 'listeners_start',
label: $gettext('Listeners'),
selectable: true,
sortable: false
},
{
key: 'delta',
label: $gettext('Change'),
selectable: true,
sortable: false
},
{
key: 'song',
isRowHeader: true,
label: $gettext('Song Title'),
selectable: true,
sortable: false
},
{
key: 'source',
label: $gettext('Source'),
selectable: true,
sortable: false
}
];
const apiUrl = computed(() => {
let apiUrl = new URL(props.baseApiUrl, document.location);
let apiUrlParams = apiUrl.searchParams;
apiUrlParams.set('start', DateTime.fromJSDate(dateRange.value.startDate).toISO());
apiUrlParams.set('end', DateTime.fromJSDate(dateRange.value.endDate).toISO());
return apiUrl.toString();
});
const exportUrl = computed(() => {
let exportUrl = new URL(apiUrl.value, document.location);
let exportUrlParams = exportUrl.searchParams;
exportUrlParams.set('format', 'csv');
return exportUrl.toString();
});
const abs = (val) => {
return Math.abs(val);
};
const $datatable = ref(); // Template Ref
const relist = () => {
$datatable.value.relist();
}; };
</script> </script>

View File

@ -1,7 +1,7 @@
<template> <template>
<b-modal <b-modal
id="streamer_broadcasts" id="streamer_broadcasts"
ref="modal" ref="$modal"
size="lg" size="lg"
centered centered
:title="$gettext('Streamer Broadcasts')" :title="$gettext('Streamer Broadcasts')"
@ -11,12 +11,12 @@
style="min-height: 40px;" style="min-height: 40px;"
class="flex-fill text-left bg-primary rounded mb-2" class="flex-fill text-left bg-primary rounded mb-2"
> >
<inline-player ref="player" /> <inline-player ref="$player" />
</div> </div>
<data-table <data-table
id="station_streamer_broadcasts" id="station_streamer_broadcasts"
ref="datatable" ref="$datatable"
:show-toolbar="false" :show-toolbar="false"
:fields="fields" :fields="fields"
:api-url="listUrl" :api-url="listUrl"
@ -65,7 +65,8 @@
</template> </template>
</b-modal> </b-modal>
</template> </template>
<script>
<script setup>
import DataTable from '~/components/Common/DataTable.vue'; import DataTable from '~/components/Common/DataTable.vue';
import formatFileSize from '~/functions/formatFileSize.js'; import formatFileSize from '~/functions/formatFileSize.js';
import InlinePlayer from '~/components/InlinePlayer'; import InlinePlayer from '~/components/InlinePlayer';
@ -74,95 +75,108 @@ import PlayButton from "~/components/Common/PlayButton";
import {DateTime} from 'luxon'; import {DateTime} from 'luxon';
import '~/vendor/sweetalert'; import '~/vendor/sweetalert';
import {useAzuraCast} from "~/vendor/azuracast"; import {useAzuraCast} from "~/vendor/azuracast";
import {ref} from "vue";
import {useTranslate} from "~/vendor/gettext";
import {useSweetAlert} from "~/vendor/sweetalert";
import {useNotify} from "~/vendor/bootstrapVue";
import {useAxios} from "~/vendor/axios";
export default { const listUrl = ref(null);
name: 'StreamerBroadcastsModal',
components: {PlayButton, Icon, InlinePlayer, DataTable},
data() {
return {
listUrl: null,
fields: [
{
key: 'download',
label: ' ',
sortable: false,
class: 'shrink pr-3'
},
{
key: 'timestampStart',
label: this.$gettext('Start Time'),
sortable: false,
formatter: (value) => {
const {timeConfig} = useAzuraCast();
return DateTime.fromSeconds(value).toLocaleString( const {$gettext} = useTranslate();
{...DateTime.DATETIME_MED, ...timeConfig} const {timeConfig} = useAzuraCast();
);
},
class: 'pl-3'
},
{
key: 'timestampEnd',
label: this.$gettext('End Time'),
sortable: false,
formatter: (value) => {
if (value === 0) {
return this.$gettext('Live');
}
const {timeConfig} = useAzuraCast(); const fields = [
{
return DateTime.fromSeconds(value).toLocaleString( key: 'download',
{...DateTime.DATETIME_MED, ...timeConfig} label: ' ',
); sortable: false,
} class: 'shrink pr-3'
},
{
key: 'size',
label: this.$gettext('Size'),
sortable: false,
formatter: (value, key, item) => {
if (!item.recording?.size) {
return '';
}
return formatFileSize(item.recording.size);
}
},
{
key: 'actions',
label: this.$gettext('Actions'),
sortable: false,
class: 'shrink'
}
]
};
}, },
methods: { {
doDelete (url) { key: 'timestampStart',
this.$confirmDelete({ label: $gettext('Start Time'),
title: this.$gettext('Delete Broadcast?') sortable: false,
}).then((result) => { formatter: (value) => {
if (result.value) { return DateTime.fromSeconds(value).toLocaleString(
this.axios.delete(url).then((resp) => { {...DateTime.DATETIME_MED, ...timeConfig}
this.$notifySuccess(resp.data.message); );
this.$refs.datatable.refresh();
});
this.$refs.datatable.refresh();
}
});
}, },
open (listUrl) { class: 'pl-3'
this.listUrl = listUrl; },
this.$refs.modal.show(); {
}, key: 'timestampEnd',
close () { label: $gettext('End Time'),
this.$refs.player.stop(); sortable: false,
formatter: (value) => {
if (value === 0) {
return $gettext('Live');
}
this.listUrl = null; return DateTime.fromSeconds(value).toLocaleString(
this.$refs.modal.hide(); {...DateTime.DATETIME_MED, ...timeConfig}
);
} }
},
{
key: 'size',
label: $gettext('Size'),
sortable: false,
formatter: (value, key, item) => {
if (!item.recording?.size) {
return '';
}
return formatFileSize(item.recording.size);
}
},
{
key: 'actions',
label: $gettext('Actions'),
sortable: false,
class: 'shrink'
} }
];
const {confirmDelete} = useSweetAlert();
const {notifySuccess} = useNotify();
const {axios} = useAxios();
const $datatable = ref(); // Template Ref
const doDelete = (url) => {
confirmDelete({
title: $gettext('Delete Broadcast?')
}).then((result) => {
if (result.value) {
axios.delete(url).then((resp) => {
notifySuccess(resp.data.message);
$datatable.value.refresh();
});
$datatable.value.refresh();
}
});
}; };
const $modal = ref(); // Template Ref
const open = (newListUrl) => {
listUrl.value = newListUrl;
$modal.value.show();
};
const $player = ref(); // Template Ref
const close = () => {
$player.value.stop();
listUrl.value = null;
$modal.value.hide();
};
defineExpose({
open
});
</script> </script>

View File

@ -5,5 +5,4 @@ const {localeWithDashes} = useAzuraCast();
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
Settings.defaultLocale = localeWithDashes; Settings.defaultLocale = localeWithDashes;
Settings.defaultZone = 'UTC';
}); });