Merge branch 'spidev' into 'master'
Pop Erweiterung auf Adressen See merge request fronk/thetool!2099
This commit is contained in:
@@ -70,6 +70,15 @@ if (!empty(trim($pops->vlan_ipv6)))
|
||||
<th>Kategorie</th>
|
||||
<td><?= $categoryArray[$pops->category]['name']." (".$categoryArray[$pops->category]['comment'].")" ?> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Adresse</th>
|
||||
<td>
|
||||
<a title="Google-Maps: <?= $pops->street ?> <?= $pops->number ?>, <?= $pops->zip ?> <?= $pops->city ?>"
|
||||
class="mapsLink"
|
||||
href="http://maps.google.com/?q=<?= urlencode($pops->street . " " . $pops->number . ", " . $pops->zip . " " . $pops->city) ?>"
|
||||
target="_blank"><?= $pops->street ?> <?= $pops->number ?>, <?= $pops->zip ?> <?= $pops->city ?></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Standort</th>
|
||||
<td>
|
||||
|
||||
@@ -112,11 +112,60 @@ if (isset($_GET['returnto']) && $_GET['returnto'] == "pop-detail") {
|
||||
<div class="form-group row">
|
||||
<label class="col-lg-2 col-form-label" for="location">Standortinfo</label>
|
||||
<div class="col-lg-10">
|
||||
<textarea id="note" class="form-control" name="location"
|
||||
<textarea id="location" class="form-control" name="location"
|
||||
rows="5"><?= $pop->location ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-lg-2 col-form-label" for="zip">Adresse</label>
|
||||
<div class="col-lg-1">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">PLZ</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="zip" id="zip"
|
||||
value="<?= $pop->zip ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">Ort</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="city" id="city"
|
||||
value="<?= $pop->city ?>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<!-- <label class="col-lg-2 col-form-label" for="street">Straße</label>-->
|
||||
<!-- <div class="col-lg-3">-->
|
||||
<!-- <input type="text" class="form-control" name="street" id="street"-->
|
||||
<!-- value="--><?php //= $pop->street ?><!--">-->
|
||||
<!-- </div>-->
|
||||
<label class="col-lg-2 col-form-label" for=""></label>
|
||||
<div class="col-lg-4">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">Straße</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="street" id="street"
|
||||
value="<?= $pop->street ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-1">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">Nr.</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="number" id="number"
|
||||
value="<?= $pop->number ?>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -52,6 +52,10 @@ class PopController extends mfBaseController
|
||||
"category" => $pop->category ?: 99,
|
||||
"networkArea" => $pop->networks,
|
||||
"location" => $pop->location,
|
||||
"zip" => $pop->zip,
|
||||
"city" => $pop->city,
|
||||
"street" => $pop->street,
|
||||
"number" => $pop->number,
|
||||
"state" => $pop->state,
|
||||
"folder_link" => $pop->folder_link,
|
||||
"doku_date" => $pop->doku_date,
|
||||
@@ -142,6 +146,7 @@ class PopController extends mfBaseController
|
||||
{
|
||||
$network_id = 90;
|
||||
$this->layout()->set("network_id", $network_id);
|
||||
$this->layout()->set("networks", NetworkModel::getAll());
|
||||
$this->layout()->set("categories", $this->getMapCategories());
|
||||
$this->layout()->setTemplate("Pop/Map");
|
||||
}
|
||||
@@ -1295,6 +1300,10 @@ class PopController extends mfBaseController
|
||||
$data['gps_lat'] = ($r->gps_lat) ? $r->gps_lat : null;
|
||||
$data['gps_long'] = ($r->gps_long) ? $r->gps_long : null;
|
||||
$data['location'] = $r->location;
|
||||
$data['zip'] = $r->zip;
|
||||
$data['city'] = $r->city;
|
||||
$data['street'] = $r->street;
|
||||
$data['number'] = $r->number;
|
||||
$data['vlan_public'] = ($r->vlan_public) ? $r->vlan_public : null;
|
||||
$data['vlan_nat'] = ($r->vlan_nat) ? $r->vlan_nat : null;
|
||||
$data['vlan_ipv6'] = ($r->vlan_ipv6) ? $r->vlan_ipv6 : null;
|
||||
@@ -1303,10 +1312,10 @@ class PopController extends mfBaseController
|
||||
$data['doku_date'] = ($r->doku_date) ? strtotime($r->doku_date) : null;
|
||||
$data['note'] = $r->note;
|
||||
|
||||
$data['edit_by'] = 1;
|
||||
// $data['edit_by'] = 1;
|
||||
|
||||
if ($mode == "add") {
|
||||
$data['create_by'] = 1;
|
||||
// $data['create_by'] = 1;
|
||||
$pop = PopModel::create($data);
|
||||
} else {
|
||||
$pop->update($data);
|
||||
@@ -1561,7 +1570,7 @@ class PopController extends mfBaseController
|
||||
$db = FronkDB::singleton();
|
||||
$pops = [];
|
||||
$popQuery = "
|
||||
SELECT DISTINCT p.id, p.name, p.gps_lat, p.gps_long
|
||||
SELECT DISTINCT p.id, p.name, p.gps_lat, p.gps_long, p.zip, p.city, p.street, p.number
|
||||
FROM Pop p
|
||||
INNER JOIN PopNetwork pn ON p.id = pn.pop_id
|
||||
INNER JOIN Network n ON pn.network_id = n.id
|
||||
@@ -1577,6 +1586,10 @@ class PopController extends mfBaseController
|
||||
'name' => $popData->name,
|
||||
'lat' => floatval($popData->gps_lat),
|
||||
'lng' => floatval($popData->gps_long),
|
||||
'zip' => $popData->zip,
|
||||
'city' => $popData->city,
|
||||
'street' => $popData->street,
|
||||
'number' => $popData->number,
|
||||
'type' => 'pop'
|
||||
];
|
||||
}
|
||||
@@ -1769,9 +1782,62 @@ class PopController extends mfBaseController
|
||||
}
|
||||
}
|
||||
|
||||
$pipes = [];
|
||||
$pipeQuery = "
|
||||
SELECT DISTINCT p.id, p.description, p.coordinates, p.type_tmp, p.coat_color, p.layer, p.status, p.state
|
||||
FROM FiberPlanPipe p
|
||||
INNER JOIN FiberPlanPipeEndpoint pe ON p.id = pe.fiberPlanPipe_id
|
||||
LEFT JOIN FiberPlanDispatcher d ON pe.fiberPlanDispatcher_id = d.id
|
||||
LEFT JOIN FiberPlanAddress a ON pe.fiberPlanAddress_id = a.id
|
||||
LEFT JOIN PopNetwork pn ON pe.pop_id = pn.pop_id
|
||||
WHERE
|
||||
(d.network_id = $network_id) OR
|
||||
(a.network_id = $network_id) OR
|
||||
(pn.network_id = $network_id)
|
||||
";
|
||||
|
||||
$pipeRes = $db->query($pipeQuery);
|
||||
if ($db->num_rows($pipeRes)) {
|
||||
while ($pipeData = $db->fetch_object($pipeRes)) {
|
||||
if (!empty($pipeData->coordinates)) {
|
||||
$coords_array = json_decode($pipeData->coordinates, true);
|
||||
if (is_array($coords_array) && count($coords_array) > 0) {
|
||||
$convertedCoords = [];
|
||||
foreach ($coords_array as $coord) {
|
||||
if (isset($coord['gps_lat']) && isset($coord['gps_long'])) {
|
||||
$convertedCoords[] = [
|
||||
'lat' => floatval($coord['gps_lat']),
|
||||
'lng' => floatval($coord['gps_long'])
|
||||
];
|
||||
} elseif (isset($coord['lat']) && isset($coord['lng'])) {
|
||||
$convertedCoords[] = [
|
||||
'lat' => floatval($coord['lat']),
|
||||
'lng' => floatval($coord['lng'])
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (count($convertedCoords) >= 2) {
|
||||
$pipes[] = [
|
||||
'id' => intval($pipeData->id),
|
||||
'name' => $pipeData->description,
|
||||
'coordinates' => $convertedCoords,
|
||||
'type' => $pipeData->type_tmp,
|
||||
'color' => $pipeData->coat_color,
|
||||
'layer' => $pipeData->layer,
|
||||
'status' => $pipeData->status,
|
||||
'state' => $pipeData->state
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mfBaseController::returnJson(mfResponse::Ok([
|
||||
'pops' => $pops,
|
||||
'cables' => $cables,
|
||||
'pipes' => $pipes,
|
||||
'distributors' => $distributors,
|
||||
'splices' => $splices,
|
||||
'customerConnections' => $customerConnections
|
||||
|
||||
@@ -8,6 +8,10 @@ class PopModel
|
||||
public $gps_lat = null;
|
||||
public $gps_long = null;
|
||||
public $location = null;
|
||||
public $zip = null;
|
||||
public $city = null;
|
||||
public $street = null;
|
||||
public $number = null;
|
||||
public $vlan_public = null;
|
||||
public $vlan_nat = null;
|
||||
public $vlan_ipv6 = null;
|
||||
|
||||
36
db/migrations/20260220100000_pop_add_address_fields.php
Normal file
36
db/migrations/20260220100000_pop_add_address_fields.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
final class PopAddAddressFields extends AbstractMigration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
$table = $this->table('Pop');
|
||||
if (!$table->hasColumn('zip')) {
|
||||
$table->addColumn('zip', 'string', ['null' => true, 'limit' => 10, 'after' => 'location']);
|
||||
}
|
||||
if (!$table->hasColumn('city')) {
|
||||
$table->addColumn('city', 'string', ['null' => true, 'limit' => 255, 'after' => 'zip']);
|
||||
}
|
||||
if (!$table->hasColumn('street')) {
|
||||
$table->addColumn('street', 'string', ['null' => true, 'limit' => 255, 'after' => 'city']);
|
||||
}
|
||||
if (!$table->hasColumn('number')) {
|
||||
$table->addColumn('number', 'string', ['null' => true, 'limit' => 20, 'after' => 'street']);
|
||||
}
|
||||
$table->update();
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
$table = $this->table('Pop');
|
||||
$table->removeColumn('zip')
|
||||
->removeColumn('city')
|
||||
->removeColumn('street')
|
||||
->removeColumn('number')
|
||||
->update();
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,12 @@ Vue.component('pop-map-modal', {
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h6 class="mb-1" :class="{ 'text-white': index === selectedIndex }">{{ pop.name }}</h6>
|
||||
</div>
|
||||
<small :class="index === selectedIndex ? 'text-white' : 'text-muted'">{{ categories[pop.category || 99] }} | {{ pop.location }}</small>
|
||||
<small :class="index === selectedIndex ? 'text-white' : 'text-muted'">
|
||||
<template v-if="pop.street || pop.city">
|
||||
{{ pop.street }} {{ pop.number }}, {{ pop.zip }} {{ pop.city }} |
|
||||
</template>
|
||||
{{ categories[pop.category || 99] }}
|
||||
</small>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -257,11 +262,15 @@ Vue.component('pop-map-modal', {
|
||||
|
||||
let categoryName = this.categories[category] || 'Unbekannt';
|
||||
let stateText = this.states[pop.state] || pop.state || '-';
|
||||
let addressHtml = (pop.street || pop.city)
|
||||
? `<div><strong>Adresse:</strong> ${pop.street || ''} ${pop.number || ''}, ${pop.zip || ''} ${pop.city || ''}</div>`
|
||||
: '';
|
||||
|
||||
const popupContent = `
|
||||
<div style="min-width: 200px;">
|
||||
<h6 class="p-0"><i class="fas fa-building"></i> <strong>${pop.name}</strong></h6>
|
||||
<hr class="my-2">
|
||||
${addressHtml}
|
||||
<div><strong>Kategorie:</strong> ${categoryName}</div>
|
||||
<div><strong>Status:</strong> ${stateText}</div>
|
||||
<div><strong>Info:</strong> ${pop.location || '-'}</div>
|
||||
@@ -300,7 +309,10 @@ Vue.component('pop-map-modal', {
|
||||
|
||||
this.filteredPops = this.allPops.filter(pop =>
|
||||
pop.name.toLowerCase().includes(query) ||
|
||||
(pop.location && pop.location.toLowerCase().includes(query))
|
||||
(pop.location && pop.location.toLowerCase().includes(query)) ||
|
||||
(pop.street && pop.street.toLowerCase().includes(query)) ||
|
||||
(pop.city && pop.city.toLowerCase().includes(query)) ||
|
||||
(pop.zip && pop.zip.toLowerCase().includes(query))
|
||||
).slice(0, 10);
|
||||
|
||||
this.showSuggestions = true;
|
||||
@@ -345,10 +357,20 @@ Vue.component('pop-map-modal', {
|
||||
this.showSuggestions = false;
|
||||
this.selectedIndex = -1;
|
||||
|
||||
let found = this.markers.find(m => m.popData.name.toLowerCase().includes(query));
|
||||
let found = this.markers.find(m =>
|
||||
m.popData.name.toLowerCase().includes(query) ||
|
||||
(m.popData.street && m.popData.street.toLowerCase().includes(query)) ||
|
||||
(m.popData.city && m.popData.city.toLowerCase().includes(query)) ||
|
||||
(m.popData.zip && m.popData.zip.toLowerCase().includes(query))
|
||||
);
|
||||
|
||||
if (!found) {
|
||||
const hiddenPop = this.allPops.find(p => p.name.toLowerCase().includes(query));
|
||||
const hiddenPop = this.allPops.find(p =>
|
||||
p.name.toLowerCase().includes(query) ||
|
||||
(p.street && p.street.toLowerCase().includes(query)) ||
|
||||
(p.city && p.city.toLowerCase().includes(query)) ||
|
||||
(p.zip && p.zip.toLowerCase().includes(query))
|
||||
);
|
||||
if (hiddenPop) {
|
||||
const category = hiddenPop.category || 99;
|
||||
if (!this.visibleCategories[category]) {
|
||||
|
||||
@@ -7,7 +7,7 @@ Vue.component('Pop', {
|
||||
<tt-table :data="window['TT_CONFIG']['POPS']" :config="PopTableConfig" excel-export>
|
||||
|
||||
<template v-slot:top-buttons>
|
||||
<button type="button" class="btn btn-primary" @click="window.location = window['TT_CONFIG']['BASE_URL'] + '/Pop/add'">
|
||||
<button type="button" class="btn btn-primary" @click="window.location = window['TT_CONFIG']['BASE_URL'] + '/Pop/add?returnto=Pop'">
|
||||
<i class="fas fa-plus"></i>
|
||||
Pop hinzufügen
|
||||
</button>
|
||||
@@ -20,6 +20,17 @@ Vue.component('Pop', {
|
||||
<a target="_blank" :href="window['TT_CONFIG']['BASE_URL'] +'/Pop/Detail?id=' + row.id">{{row.name}}</a>
|
||||
</template>
|
||||
|
||||
<template v-slot:address="{ row }">
|
||||
<a
|
||||
v-if="row.street || row.city"
|
||||
:title="'Google Maps: ' + row.street + ' ' + row.number + ', ' + row.zip + ' ' + row.city"
|
||||
class="mapsLink"
|
||||
:href="'http://maps.google.com/?q=' + row.street + ' ' + row.number + ', ' + row.zip + ' ' + row.city"
|
||||
target="_blank">
|
||||
{{row.street}} {{row.number}}, {{row.zip}} {{row.city}}
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<template v-slot:category="{ row }">
|
||||
{{ {1: 'Outdoor', 2: 'Indoor', 3: 'Sender/Funk', 4: 'Container', 99: 'Unbekannt'}[row.category] || 'Unbekannt' }}
|
||||
</template>
|
||||
@@ -78,7 +89,8 @@ Vue.component('Pop', {
|
||||
},
|
||||
{text: 'Zutritt', key: 'location', class: 'text-center', priority: 1},
|
||||
{text: 'Standort', key: 'gps', class: 'text-center', priority: 2},
|
||||
{text: 'Status', key: 'state', class: 'text-center', priority: 3, filter: 'select', filterOptions: [
|
||||
{text: 'Adresse', key: 'address', class: 'text-center', priority: 3},
|
||||
{text: 'Status', key: 'state', class: 'text-center', priority: 4, filter: 'select', filterOptions: [
|
||||
{value: '1', text: 'Planung'},
|
||||
{value: '2', text: 'Bauphase'},
|
||||
{value: '3', text: 'Grobdoku'},
|
||||
|
||||
Reference in New Issue
Block a user