225 lines
8.1 KiB
PHTML
225 lines
8.1 KiB
PHTML
<?php $this->layout('main', ['title' => __('Listeners'), 'manual' => true]) ?>
|
|
|
|
<?php
|
|
/** @var \AzuraCast\Assets $assets */
|
|
$assets
|
|
->load('vue')
|
|
->load('daterangepicker');
|
|
?>
|
|
|
|
<div class="row">
|
|
<div class="col-sm-12">
|
|
<div class="card">
|
|
<div class="card-header ch-alt">
|
|
<div class="row">
|
|
<div class="col-md-8">
|
|
<h2><?=__('Listeners') ?></h2>
|
|
<div><span id="listener-count">0</span> Unique</div>
|
|
</div>
|
|
<div class="col-md-4 text-right">
|
|
<a class="btn btn-default" id="reportrange" href="#">
|
|
<i class="zmdi zmdi-calendar"></i> <span><?=__('Live Listeners') ?></span> <i class="caret"></i>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="googlemap" style="height: 350px;">
|
|
<div class="card-body card-padding">
|
|
<?php if (empty($gmaps_api_key)): ?>
|
|
<h4><?=__('Enable Google Maps API') ?></h4>
|
|
<p><?=sprintf(__('To see a map of your listeners, provide a Google Maps API key. You can obtain one from the <a href="%s" target="_blank">Google Developer Console</a>. Make sure to enable the "Google Maps JavaScript API" as well.'), 'https://console.developers.google.com') ?></p>
|
|
|
|
<form action="" method="post">
|
|
<div class="form-group" id="field_name">
|
|
<label for="gmaps_api_key" class="control-label"><?=__('Google Maps API Key') ?>:</label>
|
|
<div class="form-field">
|
|
<input type="text" name="gmaps_api_key" class="form-control">
|
|
</div>
|
|
|
|
<input type="submit" value="<?=__('Save Changes') ?>" class="btn btn-lg btn-primary m-t-10">
|
|
</div>
|
|
</form>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
<table class="data-table table table-responsive table-striped" id="app-datatable">
|
|
<thead>
|
|
<tr>
|
|
<th><?=__('IP') ?></th>
|
|
<th><?=__('Time (sec)') ?></th>
|
|
<th><?=__('User Agent') ?></th>
|
|
<th><?=__('Location') ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="listener in listeners">
|
|
<td>{{ listener.ip }}</td>
|
|
<td>{{ listener.connected_time }}</td>
|
|
<td>
|
|
<span v-if="listener.is_mobile" title="<?=__('Mobile Device') ?>">
|
|
<i class="zmdi zmdi-smartphone"></i>
|
|
</span>
|
|
<span v-else title="<?=__('Desktop Device') ?>">
|
|
<i class="zmdi zmdi-desktop-windows"></i>
|
|
</span>
|
|
{{ listener.user_agent }}
|
|
</td>
|
|
<td>
|
|
<span v-if="listener.location.status == 'success'">
|
|
{{ listener.location.region}}, {{ listener.location.country }}
|
|
</span>
|
|
<span v-else-if="listener.location.message">
|
|
{{ listener.location.message }}
|
|
</span>
|
|
<span v-else>
|
|
<?=__('Unknown') ?>
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div class="card-body card-padding-sm text-muted">
|
|
<?=__('This product includes GeoLite2 data created by MaxMind, available from %s.', '<a href="http://www.maxmind.com">http://www.maxmind.com</a>') ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script type="text/javascript" nonce="<?=$assets->getCspNonce() ?>">
|
|
var map, live_time, load_timeout, app_datatable, gmaps_api_key, mapmarkers = {};
|
|
|
|
function cb(start, end) {
|
|
is_live = live_time.isSame(start, 'day');
|
|
|
|
if (is_live) {
|
|
$('#reportrange span').html("<?=__('Live Listeners') ?>");
|
|
} else {
|
|
$('#reportrange span').html(start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY'));
|
|
}
|
|
|
|
updateListeners(start, end);
|
|
}
|
|
|
|
function initMap() {
|
|
$(function() {
|
|
$('#googlemap').empty();
|
|
|
|
map = new google.maps.Map(document.getElementById('googlemap'), {
|
|
zoom: 2,
|
|
center: {lat: 25, lng: 12}
|
|
});
|
|
|
|
cb(live_time, live_time);
|
|
});
|
|
}
|
|
|
|
/*
|
|
* Live map updating based on parasprite-Radio by djazz:
|
|
* https://github.com/daniel-j
|
|
*/
|
|
function setMapPoints(points) {
|
|
var idlist = [];
|
|
for (i = 0; i < points.length; i++) {
|
|
var l = points[i];
|
|
|
|
if (l.location.status !== 'success')
|
|
continue;
|
|
|
|
l.id = l.location.lon + ',' + l.location.lat + ',' + l.ip;
|
|
idlist[i] = l.id;
|
|
|
|
var content = '<div style="color: black">IP: ' + l.ip + '<br>Country: ' + l.location.country + '<br>Region: ' + l.location.regionName + '<br>City: ' + l.location.city + '<br>Connected at ' + new Date(l.connected_on * 1000) + '<br>Time connected: ' + l.connected_time + '<br>User Agent: ' + l.user_agent + '</div>';
|
|
|
|
if (mapmarkers[l.id]) {
|
|
mapmarkers[l.id].infowindow.setContent(content);
|
|
continue;
|
|
}
|
|
|
|
var mark = new google.maps.Marker({
|
|
position: new google.maps.LatLng(l.location.lat, l.location.lon),
|
|
map: map,
|
|
animation: google.maps.Animation.DROP
|
|
});
|
|
|
|
mark.infowindow = new google.maps.InfoWindow({
|
|
content: content
|
|
});
|
|
|
|
mark.addListener('click', function () {
|
|
this.infowindow.open(map, this);
|
|
});
|
|
mapmarkers[l.id] = mark;
|
|
}
|
|
|
|
for (i in mapmarkers) {
|
|
if (idlist.indexOf(i) === -1) {
|
|
var mark = mapmarkers[i];
|
|
mark.setMap(null);
|
|
google.maps.event.clearListeners(mark);
|
|
|
|
mapmarkers.splice(i, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
var updateListeners = function(start, end) {
|
|
clearTimeout(load_timeout);
|
|
|
|
var params = {};
|
|
if (!is_live) {
|
|
params.start = start.format('YYYY-MM-DD');
|
|
params.end = end.format('YYYY-MM-DD');
|
|
}
|
|
|
|
$.getJSON('<?=$url->named('api:listeners:index', ['station' => $station->getId()]) ?>', params, function (data) {
|
|
app_datatable.listeners = data;
|
|
|
|
$('#listener-count').text(data.length);
|
|
|
|
if (gmaps_api_key !== '') {
|
|
setMapPoints(data);
|
|
}
|
|
|
|
if (is_live) {
|
|
load_timeout = setTimeout(updateListeners, 15 * 1000);
|
|
}
|
|
});
|
|
};
|
|
|
|
$(function() {
|
|
|
|
live_time = moment(0);
|
|
|
|
$('#reportrange').daterangepicker({
|
|
startDate: live_time,
|
|
endDate: live_time,
|
|
opens: "left",
|
|
ranges: {
|
|
"<?=__('Live Listeners') ?>": [moment(0), moment(0)],
|
|
"<?=__('Today') ?>": [moment(), moment()],
|
|
"<?=__('Yesterday') ?>": [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
|
|
"<?=__('Last 7 Days') ?>": [moment().subtract(6, 'days'), moment()],
|
|
"<?=__('Last 30 Days') ?>": [moment().subtract(29, 'days'), moment()],
|
|
"<?=__('This Month') ?>": [moment().startOf('month'), moment().endOf('month')],
|
|
"<?=__('Last Month') ?>": [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
|
|
}
|
|
}, cb);
|
|
|
|
app_datatable = new Vue({
|
|
el: '#app-datatable',
|
|
data: {
|
|
listeners: []
|
|
}
|
|
});
|
|
|
|
gmaps_api_key = "<?=$this->e($gmaps_api_key) ?>";
|
|
if (gmaps_api_key === '') {
|
|
cb(live_time, live_time);
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<?php if (!empty($gmaps_api_key)): ?>
|
|
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=<?=$this->e($gmaps_api_key) ?>&callback=initMap"></script>
|
|
<?php endif; ?>
|