Compare commits

..

2 Commits

Author SHA1 Message Date
Notoric e9b9a04a70 Styling 2024-06-11 01:21:02 +01:00
Notoric 1bc6b50727 Added graphing and heatmap 2024-06-11 01:17:06 +01:00
4 changed files with 130 additions and 8 deletions

View File

@ -74,7 +74,9 @@ class ShortlinkController extends Controller
return response()->json(['error' => 'Unauthorized'], 401);
}
$countrylist = (new Link_interactionController)->getCountryArray($id);
return view('details', ['shortlink' => $shortlink, 'countrylist' => $countrylist]);
$coordinates = Link_interaction::getCoordinates($id);
$timestamps = Link_interaction::getTimes($id);
return view('details', ['shortlink' => $shortlink, 'countrylist' => $countrylist, 'coordinates' => $coordinates, 'timestamps' => $timestamps]);
} catch (\Exception $e) {
return response()->json(['error' => $e->getMessage()], 404);
}

View File

@ -78,16 +78,21 @@ class Link_interaction extends Model
return $link_interaction;
}
public function getTimes(string $link) {
public static function getTimes(string $link) {
$link_interaction = [];
$link_interaction = Link_interaction::where('link', $link)->select('created_at')->get()->toArray();
return $link_interaction;
}
public function getCoordinates(string $link) {
$link_interaction = [];
public static function getCoordinates(string $link) {
$coordinates = [];
$link_interaction = Link_interaction::where('link', $link)->select('latitude', 'longitude')->get()->toArray();
return $link_interaction;
foreach ($link_interaction as $interaction) {
if ($interaction['latitude'] != null && $interaction['longitude'] != null) {
array_push($coordinates, $interaction);
}
}
return $coordinates;
}
}

View File

@ -10,6 +10,7 @@
body {
margin: 0;
overflow: hidden;
overflow-y: scroll;
font-family: 'Roboto', sans-serif;
background-color: var(--background);
color: white;
@ -352,7 +353,7 @@ header nav a {
display: flex;
height: 1px;
background-color: #888;
width: 500%;
width: calc(500% + 20px);
transform: translateY(5px);
}
}
@ -363,4 +364,20 @@ a button {
align-self: center;
font-size: 0.8em;
cursor: pointer;
}
}
#graphs {
display: flex;
flex-direction: row;
justify-content: space-between;
}
#graphs h2 {
margin-bottom: 20px;
}
#map {
width: 540px;
height: 400px;
}

View File

@ -4,6 +4,10 @@
Details & Logs
@endsection
@section('head')
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
@endsection
@section('content')
<div id="banner-container" class="container">
<h1>Details & Logs</h1>
@ -64,7 +68,14 @@
</form>
</div>
<div id="graphs" class="container">
<div id="map-wrapper">
<h2>Heatmap</h2>
<div id="map"></div>
</div>
<div id="timeline-wrapper">
<h2>Timeline</h2>
<canvas id="cumulativeGraph" width="540" height="400"></canvas>
</div>
</div>
<div id="stats" class="container">
<h2>Link Clicks</h2>
@ -87,4 +98,91 @@
@section('scripts')
<script src="{{ asset('js/details.js') }}"></script>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.heat/dist/leaflet-heat.js"></script>
<script>
var map = L.map('map').setView([50, 0], 3);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 10,
}).addTo(map);
var heat = L.heatLayer([], {
radius: 50,
blur: 20,
maxZoom: 3,
max: 5,
}).addTo(map);
async function loadHeatmapData() {
var data = [
@foreach ($coordinates as $coordinate)
{lat:{{ $coordinate['latitude'] }}, lng:{{ $coordinate['longitude'] }}},
@endforeach
];
heat.setLatLngs(data);
}
loadHeatmapData();
</script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns"></script>
<script>
const timestamps = [
@foreach ($timestamps as $timestamp)
'{{ $timestamp['created_at'] }}',
@endforeach
];
// Function to count occurrences cumulatively
function getCumulativeCounts(timestamps) {
const counts = [];
const dateCounts = {};
timestamps.forEach((timestamp) => {
const date = new Date(timestamp).toISOString(); // Get date part only
if (dateCounts[date]) {
dateCounts[date]++;
} else {
dateCounts[date] = 1;
}
counts.push({ date: date, count: Object.values(dateCounts).reduce((a, b) => a + b, 0) });
});
return counts;
}
// Get the cumulative data
const cumulativeData = getCumulativeCounts(timestamps);
// Extract dates and counts for the chart
const labels = cumulativeData.map(data => data.date);
const data = cumulativeData.map(data => data.count);
// Create the chart
const ctx = document.getElementById('cumulativeGraph').getContext('2d');
const cumulativeGraph = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'Total Clicks',
data: data,
borderColor: 'rgba(255, 0, 80, 1)',
backgroundColor: 'rgba(255, 0, 80, 0.2)',
borderWidth: 1,
fill: true
}]
},
options: {
scales: {
x: {
type: 'time',
time: {
unit: 'day'
}
},
y: {
beginAtZero: true
}
}
}
});
</script>
@endsection