navigation, regions
parent
50ea3f1bd8
commit
a3121bf58e
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
|
@ -63,7 +64,12 @@ class Api
|
|||
return self::get("/property/{$id}/base");
|
||||
}
|
||||
|
||||
public static function regionPropertyCapacities(int $id): mixed
|
||||
public static function regionBase(int $id): mixed
|
||||
{
|
||||
return self::get("/region/{$id}/base");
|
||||
}
|
||||
|
||||
public static function regionPropertiesCapacities(int $id): mixed
|
||||
{
|
||||
return self::get("/region/{$id}/properties/capacities");
|
||||
}
|
||||
|
|
|
@ -103,10 +103,6 @@ button[popovertarget]>span{
|
|||
isolation: isolate;
|
||||
}
|
||||
|
||||
nav>ul{
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
body>header{
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
@ -120,6 +116,45 @@ body>header{
|
|||
padding: 0 1em;
|
||||
}
|
||||
|
||||
body>header>nav{
|
||||
text-align: center;
|
||||
max-width: 10em;
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
border-radius: .2em;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
body>header>nav>ul{
|
||||
position: absolute;
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
top: -999em;
|
||||
left: -999em;
|
||||
}
|
||||
|
||||
body>header>nav:hover ul{
|
||||
top: initial;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
body>header>nav>ul>li a,
|
||||
body>header>nav>strong{
|
||||
display: inline-block;
|
||||
padding: .2em .4em;
|
||||
}
|
||||
|
||||
a{
|
||||
color: #000;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:focus{
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
|
||||
main{
|
||||
width: 100%;
|
||||
|
@ -139,7 +174,7 @@ body.overview main{
|
|||
"chart3 chart3 chart3 chart2 chart2 chart2 chart4 chart4"
|
||||
}
|
||||
|
||||
body.timeline main{
|
||||
body.property main{
|
||||
grid-template-columns: repeat(4, minmax(10%, 50%));
|
||||
grid-template-rows: repeat(3, 1fr) 4em;
|
||||
grid-template-areas:
|
||||
|
@ -149,6 +184,16 @@ body.timeline main{
|
|||
"timeline timeline timeline timeline";
|
||||
}
|
||||
|
||||
body.region main{
|
||||
grid-template-columns: repeat(4, minmax(10%, 50%));
|
||||
grid-template-rows: repeat(3, 1fr) 4em;
|
||||
grid-template-areas:
|
||||
"chart1 chart1 chart2 chart2"
|
||||
"chart1 chart1 chart3 chart4"
|
||||
"chart1 chart1 chart3 chart4"
|
||||
"chart1 chart1 timeline timeline";
|
||||
}
|
||||
|
||||
article{
|
||||
background: #f9f9f9;
|
||||
border: .0625em solid #ccc;
|
||||
|
|
|
@ -1,5 +1,15 @@
|
|||
@extends('base')
|
||||
@section('body-class', 'overview')
|
||||
@section('header')
|
||||
<nav>
|
||||
<strong>Start</strong>
|
||||
<ul>
|
||||
@foreach($regions as $r)
|
||||
<li><a href="/region/{{ $r['region_id'] }}">{{ $r['region_name'] }}</a></li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</nav>
|
||||
@endsection
|
||||
@section('main')
|
||||
<article class="header" style="grid-area: chart1;">
|
||||
<header>
|
||||
|
@ -63,19 +73,24 @@ const extractionDates = {!! json_encode($regionPropertiesCapacities['scrapeDates
|
|||
const chartHeatmap = document.getElementById('chart-heatmap');
|
||||
const cHeatmap = echarts.init(chartHeatmap);
|
||||
const cHeatmapOptions = {
|
||||
animation: false,
|
||||
tooltip: {
|
||||
position: 'top'
|
||||
},
|
||||
grid: {
|
||||
top: 30,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
left: 0
|
||||
right: 45,
|
||||
bottom: 50,
|
||||
left: 5
|
||||
},
|
||||
dataZoom: [{
|
||||
type: 'inside'
|
||||
}
|
||||
],
|
||||
type: 'slider'
|
||||
},
|
||||
{
|
||||
type: 'slider',
|
||||
show: true,
|
||||
yAxisIndex: 0,
|
||||
}],
|
||||
xAxis: {
|
||||
show: false,
|
||||
name: 'Kurzzeitmietobjekt',
|
||||
|
@ -122,8 +137,7 @@ const cHeatmapOptions = {
|
|||
},
|
||||
tooltip: {
|
||||
formatter: (data) => {
|
||||
let v = data.value
|
||||
return `Kurzzeitmietobjekte-ID: ${data.name}<br />Datum Scraping: ${extractionDates[v[1]]}<br/>Auslastung: ${v[2]} %`
|
||||
return `Kurzzeitmietobjekte-ID: ${data.data[1]}<br />Datum Scraping: ${data.data[0]}<br/>Auslastung: ${data.data[2].toFixed(2)} %`
|
||||
},
|
||||
},
|
||||
emphasis: {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
@extends('base')
|
||||
@section('body-class', 'timeline')
|
||||
|
||||
@section('body-class', 'property')
|
||||
@section('header')
|
||||
<span>Property {{ $base['property_platform_id'] }}</span><button popovertarget="prop-details"></button>
|
||||
<div popover id="prop-details">
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
@extends('base')
|
||||
@section('body-class', 'region')
|
||||
@section('header')
|
||||
<nav>
|
||||
<strong>{{ $region[0]['region_name'] }}</strong>
|
||||
<ul>
|
||||
<li><a href="/">Start</a></li>
|
||||
@foreach($regions as $r)
|
||||
@if($r['region_id'] != $region_id)
|
||||
<li><a href="/region/{{ $r['region_id'] }}">{{ $r['region_name'] }}</a></li>
|
||||
@endif
|
||||
@endforeach
|
||||
</ul>
|
||||
</nav>
|
||||
@endsection
|
||||
@section('main')
|
||||
<article style="grid-area: timeline;">
|
||||
<div id="timeline"></div>
|
||||
</article>
|
||||
<article class="header" style="grid-area: chart1;">
|
||||
<header>
|
||||
<h2 id="belegung-title"></h2>
|
||||
</header>
|
||||
<div id="chart-heatmap"></div>
|
||||
</article>
|
||||
<article class="header" style="grid-area: chart3;">
|
||||
<header>
|
||||
<h2>
|
||||
Auslastung nach Monat am 2024-04-15T07:06:22
|
||||
</h2>
|
||||
</header>
|
||||
<div id="chart-capacity-monthly">
|
||||
</div>
|
||||
</article>
|
||||
<article class="header" style="grid-area: chart2;">
|
||||
<header>
|
||||
<h2>
|
||||
Entwicklung der Auslastung
|
||||
</h2>
|
||||
<button popovertarget="chart-capacity-popover"></button>
|
||||
<div id="chart-capacity-popover" popover>
|
||||
<h2>Erkläung zum Diagramm «Entwicklung der Auslastung»</h2>
|
||||
<p>Das Liniendiagramm zeigt die Auslastung von Regionen. 100 % = die Region ist kaum ausgelastet; 100 % der Mietobjekte sind verfügbar. 0 % = Die Region ist komplett ausgelastet; Es stehen keine Mietangebote zur Verfügung.</p>
|
||||
</div>
|
||||
</header>
|
||||
<div id="chart-capacity"></div>
|
||||
</article>
|
||||
<article class="header" style="grid-area: chart4;">
|
||||
<header>
|
||||
<h2>
|
||||
Auslastung Tage für Monat
|
||||
</h2>
|
||||
</header>
|
||||
<div id="chart-capacity-daily">
|
||||
</article>
|
||||
|
||||
<script type="module">
|
||||
|
||||
const sharedOptions = {
|
||||
basic: {
|
||||
color: ['#f1eef6','#bdc9e1','#74a9cf','#2b8cbe','#045a8d'],
|
||||
grid: {
|
||||
top: 20,
|
||||
left: 60,
|
||||
right: 0,
|
||||
bottom: 50
|
||||
},
|
||||
name: (opt) => {
|
||||
return {
|
||||
name: opt.name,
|
||||
nameLocation: opt.location,
|
||||
nameGap: 24,
|
||||
nameTextStyle: {
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const chartCapacity = document.getElementById('chart-capacity');
|
||||
const cCapacity = echarts.init(chartCapacity);
|
||||
|
||||
const cCapacityOptions = {
|
||||
legend: {
|
||||
data: ['Auslastung Region', 'Auslastung alle Regionen']
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
valueFormatter: (value) => value.toFixed(2)+' %'
|
||||
},
|
||||
grid: {
|
||||
top: 20,
|
||||
left: 25,
|
||||
right: 10,
|
||||
bottom: 20,
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: {!! json_encode($regionCapacities[1]['dates']) !!},
|
||||
name: 'Zeitpunkt Scraping',
|
||||
nameLocation: 'center',
|
||||
nameGap: 24,
|
||||
nameTextStyle: {
|
||||
fontWeight: 'bold',
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
min: 0,
|
||||
max: 100,
|
||||
name: 'Auslastung in Prozent',
|
||||
nameLocation: 'center',
|
||||
nameGap: 38,
|
||||
nameTextStyle: {
|
||||
fontWeight: 'bold',
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
name: 'Auslastung alle Regionen',
|
||||
type: 'line',
|
||||
symbolSize: 7,
|
||||
data: {!! json_encode($regionCapacities[0]['capacities']) !!}
|
||||
},
|
||||
{
|
||||
name: 'Auslastung Region',
|
||||
type: 'line',
|
||||
symbolSize: 7,
|
||||
data: {!! json_encode($regionCapacities[1]['capacities']) !!}
|
||||
}]
|
||||
};
|
||||
|
||||
cCapacity.setOption(cCapacityOptions);
|
||||
|
||||
const chartHeatmap = document.getElementById('chart-heatmap');
|
||||
const cHeatmap = echarts.init(chartHeatmap);
|
||||
const cHeatmapOptions = {
|
||||
tooltip: {
|
||||
position: 'top'
|
||||
},
|
||||
grid: {
|
||||
top: 30,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
left: 0
|
||||
},
|
||||
dataZoom: [{
|
||||
type: 'inside'
|
||||
}
|
||||
],
|
||||
xAxis: {
|
||||
show: false,
|
||||
name: 'Kurzzeitmietobjekt',
|
||||
type: 'category',
|
||||
data: {!! json_encode($regionPropertiesCapacities['scrapeDates']) !!},
|
||||
splitArea: {
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
show: true,
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
show: false,
|
||||
type: 'category',
|
||||
data: {!! json_encode($regionPropertiesCapacities['property_ids']) !!},
|
||||
splitArea: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
visualMap: {
|
||||
type: 'piecewise',
|
||||
min: 0,
|
||||
max: 100,
|
||||
calculable: true,
|
||||
orient: 'horizontal',
|
||||
left: 'center',
|
||||
top: 0,
|
||||
formatter: (v1, v2) => {
|
||||
return `${v1} – ${v2} %`;
|
||||
},
|
||||
inRange: {
|
||||
color: sharedOptions.basic.color,
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Auslastung',
|
||||
type: 'heatmap',
|
||||
blurSize: 0,
|
||||
data: {!! json_encode($regionPropertiesCapacities['values']) !!},
|
||||
label: {
|
||||
show: false
|
||||
},
|
||||
tooltip: {
|
||||
formatter: (data) => {
|
||||
let v = data.value
|
||||
return `Kurzzeitmietobjekte-ID: ${data.name}<br />Datum Scraping: ${extractionDates[v[1]]}<br/>Auslastung: ${v[2]} %`
|
||||
},
|
||||
},
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
borderColor: '#000',
|
||||
borderWidth: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
cHeatmap.setOption(cHeatmapOptions);
|
||||
</script>
|
||||
@endsection
|
|
@ -5,7 +5,9 @@ use App\Api;
|
|||
|
||||
Route::get('/', function () {
|
||||
|
||||
$regionPropertyCapacities = Api::regionPropertyCapacities(-1);
|
||||
$regionBase = Api::regionBase(-1);
|
||||
$regionBase[] = ['region_name' => 'Alle Regionen', 'region_id' => -1];
|
||||
$regionPropertyCapacities = Api::regionPropertiesCapacities(-1);
|
||||
$propertiesGrowth = Api::propertiesGrowth();
|
||||
$propsPerRegion = Api::propertiesPerRegion();
|
||||
$propsPerRegionName = [];
|
||||
|
@ -18,7 +20,7 @@ Route::get('/', function () {
|
|||
|
||||
$propertiesGeo = Api::propertiesGeo();
|
||||
|
||||
return view('overview', ["regionPropertiesCapacities" => $regionPropertyCapacities, "geo" => $propertiesGeo, "growth" => $propertiesGrowth, "propsPerRegion" => [json_encode($propsPerRegionName), json_encode($propsPerRegionCounts)]]);
|
||||
return view('overview', ["regions" => $regionBase, "regionPropertiesCapacities" => $regionPropertyCapacities, "geo" => $propertiesGeo, "growth" => $propertiesGrowth, "propsPerRegion" => [json_encode($propsPerRegionName), json_encode($propsPerRegionCounts)]]);
|
||||
});
|
||||
|
||||
Route::get('/prop/{id}', function (int $id) {
|
||||
|
@ -85,11 +87,16 @@ Route::get('/prop/{id}', function (int $id) {
|
|||
|
||||
Route::get('/region/{id}', function (int $id) {
|
||||
|
||||
$regionBaseAll = Api::regionBase(-1);
|
||||
$regionBaseAll[] = ['region_name' => 'Alle Regionen', 'region_id' => -1];
|
||||
$regionBaseRegion = $id >= 0 ? Api::regionBase($id) : [['region_name' => 'Alle Regionen']];
|
||||
|
||||
$regionPropertiesCapacities = Api::regionPropertiesCapacities($id);
|
||||
$regionCapacitiesRegion = Api::regionCapacities($id);
|
||||
$regionCapacitiesAll = Api::regionCapacities(-1);
|
||||
$regionCapacities = [$regionCapacitiesAll, $regionCapacitiesRegion];
|
||||
|
||||
return view('region', ['regionCapacities' => $regionCapacities]);
|
||||
return view('region', ['regions' => $regionBaseAll, 'region' => $regionBaseRegion, 'region_id' => $id, 'regionCapacities' => $regionCapacities, 'regionPropertiesCapacities' => $regionPropertiesCapacities]);
|
||||
|
||||
|
||||
});
|
||||
|
|
|
@ -87,6 +87,10 @@ def region_capacities_data(id: int, startDate: str):
|
|||
result = etl_rmA.region_movingAverage(id, startDate)
|
||||
return result
|
||||
|
||||
@app.get("/region/{id}/base")
|
||||
def region_base_data(id: int):
|
||||
return d.region_base_data(id).pl().to_dicts()
|
||||
|
||||
@app.get("/region/{id}/properties/capacities")
|
||||
def region_property_capacities_data(id: int):
|
||||
capacities = etl_rpc.region_properties_capacities(id)
|
||||
|
|
Loading…
Reference in New Issue