Hranice sboru
parent
6d22e07ccf
commit
5185e5efb0
|
|
@ -10,6 +10,6 @@ final class Konstanty
|
||||||
* Verze aplikace.
|
* Verze aplikace.
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
public const verze = '1.4';
|
public const verze = '1.8';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,208 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Model;
|
||||||
|
|
||||||
|
use Nette\Database\Explorer;
|
||||||
|
use Nette\Utils\Json;
|
||||||
|
use Nette\Utils\JsonException;
|
||||||
|
use SimpleXMLElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hranice sboru. V tabulce je jeden záznam, nový KML ho nahradí.
|
||||||
|
*/
|
||||||
|
final class SborFacade
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private Explorer $database,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array{nazev: string, bodu: int}|null
|
||||||
|
*/
|
||||||
|
public function getSbor(): ?array
|
||||||
|
{
|
||||||
|
$radek = $this->database->fetch('SELECT TOP 1 NAZEV, GEO FROM SBOR ORDER BY ID');
|
||||||
|
if ($radek === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$geo = Json::decode((string) $radek->GEO, forceArrays: true);
|
||||||
|
} catch (JsonException) {
|
||||||
|
$geo = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'nazev' => (string) $radek->NAZEV,
|
||||||
|
'bodu' => is_array($geo) ? $this->pocetBodu($geo) : 0,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GeoJSON geometrie jediné uložené hranice sboru.
|
||||||
|
*/
|
||||||
|
public function getGeoJson(): ?string
|
||||||
|
{
|
||||||
|
$geo = $this->database->fetchField('SELECT TOP 1 GEO FROM SBOR ORDER BY ID');
|
||||||
|
if (!is_string($geo) || trim($geo) === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $geo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function nahradZKml(string $kml): void
|
||||||
|
{
|
||||||
|
$nazev = $this->nazevZKml($kml);
|
||||||
|
$geo = Json::encode($this->geometrieZKml($kml));
|
||||||
|
|
||||||
|
$id = $this->database->fetchField('SELECT TOP 1 ID FROM SBOR ORDER BY ID');
|
||||||
|
if ($id === null) {
|
||||||
|
$this->database->query('INSERT INTO SBOR (NAZEV, GEO) VALUES (?, ?)', $nazev, $geo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->database->query('UPDATE SBOR SET NAZEV = ?, GEO = ? WHERE ID = ?', $nazev, $geo, $id);
|
||||||
|
$this->database->query('DELETE FROM SBOR WHERE ID <> ?', $id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function nazevZKml(string $kml): string
|
||||||
|
{
|
||||||
|
$xml = $this->nactiKml($kml);
|
||||||
|
$nazvy = $xml->xpath('//k:Document/k:name');
|
||||||
|
if ($nazvy === false || $nazvy === []) {
|
||||||
|
$nazvy = $xml->xpath('//k:Placemark/k:name');
|
||||||
|
}
|
||||||
|
$nazev = trim((string) ($nazvy[0] ?? ''));
|
||||||
|
if ($nazev === '') {
|
||||||
|
throw new \InvalidArgumentException('V souboru KML chybí název sboru.');
|
||||||
|
}
|
||||||
|
if (mb_strlen($nazev) > 50) {
|
||||||
|
throw new \InvalidArgumentException('Název sboru v souboru je delší než 50 znaků.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $nazev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array{type: string, coordinates: array<int, mixed>}
|
||||||
|
*/
|
||||||
|
private function geometrieZKml(string $kml): array
|
||||||
|
{
|
||||||
|
$xml = $this->nactiKml($kml);
|
||||||
|
$uzly = $xml->xpath('//k:Polygon/k:outerBoundaryIs/k:LinearRing/k:coordinates');
|
||||||
|
if ($uzly === false || $uzly === []) {
|
||||||
|
throw new \InvalidArgumentException('V souboru KML není polygon s hranicí.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$prstence = [];
|
||||||
|
foreach ($uzly as $uzel) {
|
||||||
|
$prstence[] = $this->prstenec((string) $uzel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($prstence) === 1) {
|
||||||
|
return [
|
||||||
|
'type' => 'Polygon',
|
||||||
|
'coordinates' => [$prstence[0]],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'type' => 'MultiPolygon',
|
||||||
|
'coordinates' => array_map(
|
||||||
|
static fn(array $prstenec): array => [$prstenec],
|
||||||
|
$prstence,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function nactiKml(string $kml): SimpleXMLElement
|
||||||
|
{
|
||||||
|
$kml = trim($kml);
|
||||||
|
if ($kml === '' || !str_contains($kml, '<kml')) {
|
||||||
|
throw new \InvalidArgumentException('Soubor není ve formátu KML.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$predchozi = libxml_use_internal_errors(true);
|
||||||
|
try {
|
||||||
|
$xml = simplexml_load_string($kml, SimpleXMLElement::class, LIBXML_NONET);
|
||||||
|
} finally {
|
||||||
|
libxml_clear_errors();
|
||||||
|
libxml_use_internal_errors($predchozi);
|
||||||
|
}
|
||||||
|
if (!$xml instanceof SimpleXMLElement) {
|
||||||
|
throw new \InvalidArgumentException('Soubor KML se nepodařilo přečíst.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$xml->registerXPathNamespace('k', 'http://www.opengis.net/kml/2.2');
|
||||||
|
return $xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list<array{0: float, 1: float}>
|
||||||
|
*/
|
||||||
|
private function prstenec(string $text): array
|
||||||
|
{
|
||||||
|
$kruh = [];
|
||||||
|
foreach (preg_split('/\s+/', trim($text)) ?: [] as $token) {
|
||||||
|
if ($token === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$casti = explode(',', $token);
|
||||||
|
if (count($casti) < 2 || !is_numeric($casti[0]) || !is_numeric($casti[1])) {
|
||||||
|
throw new \InvalidArgumentException('Bod hranice v KML nemá souřadnice.');
|
||||||
|
}
|
||||||
|
$lng = round((float) $casti[0], 7);
|
||||||
|
$lat = round((float) $casti[1], 7);
|
||||||
|
if ($lng < 12.0 || $lng > 19.0 || $lat < 48.0 || $lat > 52.0) {
|
||||||
|
throw new \InvalidArgumentException('Bod hranice sboru je mimo oblast obvodů.');
|
||||||
|
}
|
||||||
|
$kruh[] = [$lng, $lat];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($kruh) > 1 && $kruh[0] === $kruh[count($kruh) - 1]) {
|
||||||
|
array_pop($kruh);
|
||||||
|
}
|
||||||
|
if (count($kruh) < 3) {
|
||||||
|
throw new \InvalidArgumentException('Hranice sboru musí mít aspoň tři body.');
|
||||||
|
}
|
||||||
|
if (count($kruh) > 50000) {
|
||||||
|
throw new \InvalidArgumentException('Hranice sboru má příliš mnoho bodů.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$kruh[] = $kruh[0];
|
||||||
|
return $kruh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $geo
|
||||||
|
*/
|
||||||
|
private function pocetBodu(array $geo): int
|
||||||
|
{
|
||||||
|
$prstence = [];
|
||||||
|
if (($geo['type'] ?? '') === 'Polygon') {
|
||||||
|
$prstence[] = $geo['coordinates'][0] ?? [];
|
||||||
|
} elseif (($geo['type'] ?? '') === 'MultiPolygon') {
|
||||||
|
foreach ($geo['coordinates'] ?? [] as $polygon) {
|
||||||
|
$prstence[] = $polygon[0] ?? [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$pocet = 0;
|
||||||
|
foreach ($prstence as $kruh) {
|
||||||
|
if (!is_array($kruh)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$delka = count($kruh);
|
||||||
|
if ($delka > 1 && $kruh[0] === $kruh[$delka - 1]) {
|
||||||
|
$delka--;
|
||||||
|
}
|
||||||
|
$pocet += $delka;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pocet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,11 +5,13 @@ declare(strict_types=1);
|
||||||
namespace App\Presentation\Administrace;
|
namespace App\Presentation\Administrace;
|
||||||
|
|
||||||
use App\Model\LoginFacade;
|
use App\Model\LoginFacade;
|
||||||
|
use App\Model\SborFacade;
|
||||||
use App\Presentation\BasePresenter;
|
use App\Presentation\BasePresenter;
|
||||||
use Nette;
|
use Nette;
|
||||||
use Nette\Application\UI\Form;
|
use Nette\Application\UI\Form;
|
||||||
use Nette\Application\UI\Multiplier;
|
use Nette\Application\UI\Multiplier;
|
||||||
use Nette\Database\Row;
|
use Nette\Database\Row;
|
||||||
|
use Nette\Http\FileUpload;
|
||||||
use Nette\Utils\ArrayHash;
|
use Nette\Utils\ArrayHash;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -19,6 +21,7 @@ final class AdministracePresenter extends BasePresenter
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private LoginFacade $uzivatele,
|
private LoginFacade $uzivatele,
|
||||||
|
private SborFacade $sbor,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,6 +55,50 @@ final class AdministracePresenter extends BasePresenter
|
||||||
|
|
||||||
$this->template->stav = $this->stav;
|
$this->template->stav = $this->stav;
|
||||||
$this->template->uzivatele = $uzivatele;
|
$this->template->uzivatele = $uzivatele;
|
||||||
|
$this->template->sbor = $this->sbor->getSbor();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function createComponentSborForm(): Form
|
||||||
|
{
|
||||||
|
$form = new Form;
|
||||||
|
$form->addUpload('soubor', 'Soubor KML')
|
||||||
|
->setRequired('Vyberte soubor KML.')
|
||||||
|
->setHtmlAttribute('accept', '.kml,application/vnd.google-earth.kml+xml');
|
||||||
|
$form->addSubmit('send', 'Nahrát');
|
||||||
|
$form->addProtection('Platnost formuláře vypršela, odešlete ho znovu.');
|
||||||
|
$form->onSuccess[] = $this->sborFormSucceeded(...);
|
||||||
|
return $form;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sborFormSucceeded(Form $form, ArrayHash $values): void
|
||||||
|
{
|
||||||
|
$soubor = $values->soubor;
|
||||||
|
if (!$soubor instanceof FileUpload || !$soubor->isOk()) {
|
||||||
|
$form->addError('Soubor se nepodařilo nahrát.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pripona = strtolower(pathinfo($soubor->getUntrustedName(), PATHINFO_EXTENSION));
|
||||||
|
if ($pripona !== 'kml') {
|
||||||
|
$form->addError('Nahrajte soubor ve formátu KML.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$obsah = $soubor->getContents();
|
||||||
|
if (!is_string($obsah) || $obsah === '') {
|
||||||
|
$form->addError('Soubor KML je prázdný.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->sbor->nahradZKml($obsah);
|
||||||
|
} catch (\InvalidArgumentException $e) {
|
||||||
|
$form->addError($e->getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->flashMessage('Hranice sboru byly uloženy.');
|
||||||
|
$this->redirect('this');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createComponentNovyForm(): Form
|
protected function createComponentNovyForm(): Form
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,20 @@
|
||||||
</table>
|
</table>
|
||||||
<p class="prazdno" n:if="count($uzivatele) === 0">V tomto filtru není žádný uživatel.</p>
|
<p class="prazdno" n:if="count($uzivatele) === 0">V tomto filtru není žádný uživatel.</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section class="panel">
|
||||||
|
<h2>Hranice sboru</h2>
|
||||||
|
<p class="lista-popis" n:if="$sbor">Uloženo: {$sbor['nazev']}. Hranice má {$sbor['bodu']} bodů. Nový soubor KML tyhle body nahradí.</p>
|
||||||
|
<p class="lista-popis" n:if="!$sbor">Hranice sboru zatím nejsou nahrané. Nahrajte soubor KML.</p>
|
||||||
|
<form n:name="sborForm" class="sbor-formular">
|
||||||
|
<div class="alert alert-danger" n:if="$form->hasErrors()" n:foreach="$form->getErrors() as $error">{$error}</div>
|
||||||
|
<label n:name="soubor" class="form-label">Soubor KML</label>
|
||||||
|
<div class="formular-akce">
|
||||||
|
<input n:name="soubor">
|
||||||
|
<button n:name="send" class="tlacitko is-aktivni">{if $sbor}Nahradit{else}Nahrát{/if}</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal fade" id="modalNovy" tabindex="-1" aria-labelledby="modalNovyLabel" aria-hidden="true" data-show-errors="{if $presenter['novyForm']->hasErrors()}1{else}0{/if}">
|
<div class="modal fade" id="modalNovy" tabindex="-1" aria-labelledby="modalNovyLabel" aria-hidden="true" data-show-errors="{if $presenter['novyForm']->hasErrors()}1{else}0{/if}">
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ namespace App\Presentation\Mapa;
|
||||||
|
|
||||||
use App\Core\Konstanty;
|
use App\Core\Konstanty;
|
||||||
use App\Model\ObvodFacade;
|
use App\Model\ObvodFacade;
|
||||||
|
use App\Model\SborFacade;
|
||||||
use App\Model\ZaznamFacade;
|
use App\Model\ZaznamFacade;
|
||||||
use Nette;
|
use Nette;
|
||||||
use Nette\Application\Responses\TextResponse;
|
use Nette\Application\Responses\TextResponse;
|
||||||
|
|
@ -23,6 +24,7 @@ final class MapaPresenter extends Nette\Application\UI\Presenter
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private ZaznamFacade $zaznam,
|
private ZaznamFacade $zaznam,
|
||||||
private ObvodFacade $obvod,
|
private ObvodFacade $obvod,
|
||||||
|
private SborFacade $sbor,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,7 +52,7 @@ final class MapaPresenter extends Nette\Application\UI\Presenter
|
||||||
public function renderDefault(?int $obvod = null, ?string $filtr = null): void
|
public function renderDefault(?int $obvod = null, ?string $filtr = null): void
|
||||||
{
|
{
|
||||||
$prihlaseny = $this->getUser()->isLoggedIn();
|
$prihlaseny = $this->getUser()->isLoggedIn();
|
||||||
$povolene = ['obvody', 'stari', 'nedokoncene'];
|
$povolene = ['obvody', 'sbor', 'stari', 'nedokoncene'];
|
||||||
if (!$prihlaseny || !in_array($filtr, $povolene, true)) {
|
if (!$prihlaseny || !in_array($filtr, $povolene, true)) {
|
||||||
$filtr = 'obvody';
|
$filtr = 'obvody';
|
||||||
}
|
}
|
||||||
|
|
@ -70,5 +72,6 @@ final class MapaPresenter extends Nette\Application\UI\Presenter
|
||||||
$this->template->maxMesicu = self::STUPNICE_MESICU;
|
$this->template->maxMesicu = self::STUPNICE_MESICU;
|
||||||
$this->template->maxPrideleni = self::STUPNICE_PRIDELENI;
|
$this->template->maxPrideleni = self::STUPNICE_PRIDELENI;
|
||||||
$this->template->stariJson = Json::encode($stari, htmlSafe: true, forceObjects: true);
|
$this->template->stariJson = Json::encode($stari, htmlSafe: true, forceObjects: true);
|
||||||
|
$this->template->sborJson = $this->sbor->getGeoJson() ?? 'null';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,5 +11,6 @@
|
||||||
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.css" />
|
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.css" />
|
||||||
<script src="https://unpkg.com/leaflet.markercluster@1.5.3/dist/leaflet.markercluster.js"></script>
|
<script src="https://unpkg.com/leaflet.markercluster@1.5.3/dist/leaflet.markercluster.js"></script>
|
||||||
<script type="application/json" id="stari-data">{$stariJson|noescape}</script>
|
<script type="application/json" id="stari-data">{$stariJson|noescape}</script>
|
||||||
|
<script type="application/json" id="sbor-data">{$sborJson|noescape}</script>
|
||||||
<script src="{$basePath}/js/stari.js?v={$appVersion ?? '1.0'}"></script>
|
<script src="{$basePath}/js/stari.js?v={$appVersion ?? '1.0'}"></script>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ namespace App\Presentation\Obvod;
|
||||||
|
|
||||||
use App\Model\LoginFacade;
|
use App\Model\LoginFacade;
|
||||||
use App\Model\ObvodFacade;
|
use App\Model\ObvodFacade;
|
||||||
|
use App\Model\SborFacade;
|
||||||
use App\Model\ZaznamFacade;
|
use App\Model\ZaznamFacade;
|
||||||
use App\Presentation\BasePresenter;
|
use App\Presentation\BasePresenter;
|
||||||
use App\Presentation\Mapa\MapaPresenter;
|
use App\Presentation\Mapa\MapaPresenter;
|
||||||
|
|
@ -37,6 +38,7 @@ final class ObvodPresenter extends BasePresenter
|
||||||
private ObvodFacade $obvod,
|
private ObvodFacade $obvod,
|
||||||
private ZaznamFacade $zaznam,
|
private ZaznamFacade $zaznam,
|
||||||
private LoginFacade $uzivatele,
|
private LoginFacade $uzivatele,
|
||||||
|
private SborFacade $sbor,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,6 +120,7 @@ final class ObvodPresenter extends BasePresenter
|
||||||
public function renderHranice(int $id): void
|
public function renderHranice(int $id): void
|
||||||
{
|
{
|
||||||
$this->template->obvod = $this->obvod->getObvod($id);
|
$this->template->obvod = $this->obvod->getObvod($id);
|
||||||
|
$this->template->sborJson = $this->sbor->getGeoJson() ?? 'null';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createComponentHraniceForm(): Form
|
protected function createComponentHraniceForm(): Form
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
data-geojson="{link :Mapa:geojson}"
|
data-geojson="{link :Mapa:geojson}"
|
||||||
data-obvod="{$obvod->CISLO}"></div>
|
data-obvod="{$obvod->CISLO}"></div>
|
||||||
<div class="hranice-lista">
|
<div class="hranice-lista">
|
||||||
<p class="hranice-napoveda">Modrý je obvod {$obvod->CISLO}. Kolečko táhni, menší kroužek na hraně bod přidá. Vybraný bod odebere tlačítko.</p>
|
<p class="hranice-napoveda">Modrý je obvod {$obvod->CISLO}.{if $sborJson !== 'null'} Hnědá čára je hranice sboru.{/if} Kolečko táhni, menší kroužek na hraně bod přidá. Vybraný bod odebere tlačítko.</p>
|
||||||
<p class="hranice-chyba" n:if="$presenter['hraniceForm']->hasErrors()" n:foreach="$presenter['hraniceForm']->getErrors() as $error">{$error}</p>
|
<p class="hranice-chyba" n:if="$presenter['hraniceForm']->hasErrors()" n:foreach="$presenter['hraniceForm']->getErrors() as $error">{$error}</p>
|
||||||
<form n:name="hraniceForm" class="hranice-akce">
|
<form n:name="hraniceForm" class="hranice-akce">
|
||||||
<input n:name="geo">
|
<input n:name="geo">
|
||||||
|
|
@ -14,5 +14,6 @@
|
||||||
<a n:href="view id: $obvod->ID" class="tlacitko tlacitko-zrusit">Zrušit</a>
|
<a n:href="view id: $obvod->ID" class="tlacitko tlacitko-zrusit">Zrušit</a>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
<script type="application/json" id="sbor-data">{$sborJson|noescape}</script>
|
||||||
<script src="{$basePath}/js/hranice.js?v={$appVersion ?? '1.0'}"></script>
|
<script src="{$basePath}/js/hranice.js?v={$appVersion ?? '1.0'}"></script>
|
||||||
{/block}
|
{/block}
|
||||||
|
|
|
||||||
|
|
@ -765,6 +765,21 @@ body:has(#map[data-max]) {
|
||||||
margin-top: 0.4rem;
|
margin-top: 0.4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sbor-formular .form-label {
|
||||||
|
color: #1d4f91;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sbor-formular input[type="file"] {
|
||||||
|
max-width: 32rem;
|
||||||
|
padding: 0.45rem 0.6rem;
|
||||||
|
border: 2px solid #1d4f91;
|
||||||
|
border-radius: 0.8rem;
|
||||||
|
background: #fff;
|
||||||
|
color: #1d4f91;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
.podklady {
|
.podklady {
|
||||||
border: 0;
|
border: 0;
|
||||||
margin: 0 0 0.85rem;
|
margin: 0 0 0.85rem;
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,25 @@
|
||||||
},
|
},
|
||||||
}).addTo(map);
|
}).addTo(map);
|
||||||
|
|
||||||
|
var sborEl = document.getElementById('sbor-data');
|
||||||
|
if (sborEl && sborEl.textContent && sborEl.textContent.trim() !== 'null') {
|
||||||
|
try {
|
||||||
|
var sbor = L.geoJSON(JSON.parse(sborEl.textContent), {
|
||||||
|
interactive: false,
|
||||||
|
style: {
|
||||||
|
color: '#8a3b12',
|
||||||
|
weight: 4,
|
||||||
|
opacity: 1,
|
||||||
|
fillColor: '#f4d7b0',
|
||||||
|
fillOpacity: 0.2,
|
||||||
|
},
|
||||||
|
}).addTo(map);
|
||||||
|
sbor.bringToBack();
|
||||||
|
} catch (e) {
|
||||||
|
// hranice sboru zůstane nezobrazená
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var vlastni = null;
|
var vlastni = null;
|
||||||
(data.features || []).some(function (feature) {
|
(data.features || []).some(function (feature) {
|
||||||
if (feature.properties && String(feature.properties.number) === String(obvodId)) {
|
if (feature.properties && String(feature.properties.number) === String(obvodId)) {
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,20 @@
|
||||||
var obvodId = mapaEl.getAttribute('data-obvod');
|
var obvodId = mapaEl.getAttribute('data-obvod');
|
||||||
var prihlaseny = mapaEl.getAttribute('data-prihlaseny') === '1';
|
var prihlaseny = mapaEl.getAttribute('data-prihlaseny') === '1';
|
||||||
var rezim = mapaEl.getAttribute('data-filtr');
|
var rezim = mapaEl.getAttribute('data-filtr');
|
||||||
if (!prihlaseny || (rezim !== 'stari' && rezim !== 'nedokoncene')) {
|
if (!prihlaseny || (rezim !== 'stari' && rezim !== 'nedokoncene' && rezim !== 'sbor')) {
|
||||||
rezim = 'obvody';
|
rezim = 'obvody';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sborData = null;
|
||||||
|
var sborEl = document.getElementById('sbor-data');
|
||||||
|
if (sborEl && sborEl.textContent && sborEl.textContent.trim() !== 'null') {
|
||||||
|
try {
|
||||||
|
sborData = JSON.parse(sborEl.textContent);
|
||||||
|
} catch (e) {
|
||||||
|
sborData = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var ZELENA = [27, 158, 62];
|
var ZELENA = [27, 158, 62];
|
||||||
var ZLUTA = [230, 184, 0];
|
var ZLUTA = [230, 184, 0];
|
||||||
var CERVENA = [198, 40, 40];
|
var CERVENA = [198, 40, 40];
|
||||||
|
|
@ -67,7 +77,7 @@
|
||||||
|
|
||||||
function style(feature) {
|
function style(feature) {
|
||||||
var info = infoObvodu(feature);
|
var info = infoObvodu(feature);
|
||||||
if (rezim === 'obvody') {
|
if (rezim === 'obvody' || rezim === 'sbor') {
|
||||||
return {
|
return {
|
||||||
fillColor: MODRA_PLOCHA,
|
fillColor: MODRA_PLOCHA,
|
||||||
color: '#1d4f91',
|
color: '#1d4f91',
|
||||||
|
|
@ -146,7 +156,8 @@
|
||||||
div.innerHTML =
|
div.innerHTML =
|
||||||
'<button type="button" data-rezim="obvody">Obvody</button>' +
|
'<button type="button" data-rezim="obvody">Obvody</button>' +
|
||||||
'<button type="button" data-rezim="stari">Nepropracované</button>' +
|
'<button type="button" data-rezim="stari">Nepropracované</button>' +
|
||||||
'<button type="button" data-rezim="nedokoncene">Rozpracované</button>';
|
'<button type="button" data-rezim="nedokoncene">Rozpracované</button>' +
|
||||||
|
'<button type="button" data-rezim="sbor">Sbor</button>';
|
||||||
L.DomEvent.disableClickPropagation(div);
|
L.DomEvent.disableClickPropagation(div);
|
||||||
filtrTlacitka = div.querySelectorAll('button');
|
filtrTlacitka = div.querySelectorAll('button');
|
||||||
filtrTlacitka.forEach(function (tlacitko) {
|
filtrTlacitka.forEach(function (tlacitko) {
|
||||||
|
|
@ -186,7 +197,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function htmlZnacky(cislo, info) {
|
function htmlZnacky(cislo, info) {
|
||||||
if (rezim === 'obvody') {
|
if (rezim === 'obvody' || rezim === 'sbor') {
|
||||||
return '<div class="obvod-znacka-telo"><div class="obvod-kolecko" style="background:' + MODRA + ';border-color:#1d4f91;color:#fff">' + cislo + '</div></div>';
|
return '<div class="obvod-znacka-telo"><div class="obvod-kolecko" style="background:' + MODRA + ';border-color:#1d4f91;color:#fff">' + cislo + '</div></div>';
|
||||||
}
|
}
|
||||||
if (rezim === 'nedokoncene') {
|
if (rezim === 'nedokoncene') {
|
||||||
|
|
@ -221,7 +232,7 @@
|
||||||
disableClusteringAtZoom: 17,
|
disableClusteringAtZoom: 17,
|
||||||
iconCreateFunction: function (cluster) {
|
iconCreateFunction: function (cluster) {
|
||||||
var pocet = cluster.getChildCount();
|
var pocet = cluster.getChildCount();
|
||||||
if (rezim === 'obvody') {
|
if (rezim === 'obvody' || rezim === 'sbor') {
|
||||||
return L.divIcon({
|
return L.divIcon({
|
||||||
className: 'obvod-skupina',
|
className: 'obvod-skupina',
|
||||||
html: '<div class="obvod-skupina-telo"><div class="obvod-kolecko" style="background:#1b9e3e;border-color:#146b2b;color:#fff">' + pocet + 'x</div></div>',
|
html: '<div class="obvod-skupina-telo"><div class="obvod-kolecko" style="background:#1b9e3e;border-color:#146b2b;color:#fff">' + pocet + 'x</div></div>',
|
||||||
|
|
@ -531,6 +542,27 @@
|
||||||
|
|
||||||
var geojson = null;
|
var geojson = null;
|
||||||
var geoData = null;
|
var geoData = null;
|
||||||
|
var sborVrstva = null;
|
||||||
|
|
||||||
|
function nakresliSbor() {
|
||||||
|
if (sborVrstva) {
|
||||||
|
map.removeLayer(sborVrstva);
|
||||||
|
sborVrstva = null;
|
||||||
|
}
|
||||||
|
if (rezim !== 'sbor' || !sborData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sborVrstva = L.geoJSON(sborData, {
|
||||||
|
interactive: false,
|
||||||
|
style: {
|
||||||
|
color: '#8a3b12',
|
||||||
|
weight: 4,
|
||||||
|
opacity: 1,
|
||||||
|
fillColor: '#f4d7b0',
|
||||||
|
fillOpacity: 0.2,
|
||||||
|
},
|
||||||
|
}).addTo(map);
|
||||||
|
}
|
||||||
|
|
||||||
function filtrObvodu(feature) {
|
function filtrObvodu(feature) {
|
||||||
if (!obvodId) {
|
if (!obvodId) {
|
||||||
|
|
@ -556,8 +588,8 @@
|
||||||
tlacitko.classList.toggle('is-active', tlacitko.getAttribute('data-rezim') === rezim);
|
tlacitko.classList.toggle('is-active', tlacitko.getAttribute('data-rezim') === rezim);
|
||||||
});
|
});
|
||||||
if (legendaEl) {
|
if (legendaEl) {
|
||||||
legendaEl.style.display = rezim === 'obvody' ? 'none' : '';
|
legendaEl.style.display = rezim === 'obvody' || rezim === 'sbor' ? 'none' : '';
|
||||||
if (rezim !== 'obvody') {
|
if (rezim !== 'obvody' && rezim !== 'sbor') {
|
||||||
legendaEl.innerHTML = obsahLegendy();
|
legendaEl.innerHTML = obsahLegendy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -571,20 +603,26 @@
|
||||||
map.removeLayer(znacky);
|
map.removeLayer(znacky);
|
||||||
}
|
}
|
||||||
znacky = vytvorSkupinu();
|
znacky = vytvorSkupinu();
|
||||||
|
nakresliSbor();
|
||||||
geojson = L.geoJSON(geoData, {
|
geojson = L.geoJSON(geoData, {
|
||||||
style: style,
|
style: style,
|
||||||
filter: filtrObvodu,
|
filter: filtrObvodu,
|
||||||
onEachFeature: onEachFeature,
|
onEachFeature: onEachFeature,
|
||||||
}).addTo(map);
|
}).addTo(map);
|
||||||
|
if (sborVrstva) {
|
||||||
|
sborVrstva.bringToBack();
|
||||||
|
}
|
||||||
znacky.addTo(map);
|
znacky.addTo(map);
|
||||||
oznacFiltr();
|
oznacFiltr();
|
||||||
if (poprve && geojson.getLayers().length) {
|
if (rezim === 'sbor' && sborVrstva && sborVrstva.getBounds().isValid() && !obvodId) {
|
||||||
|
map.fitBounds(sborVrstva.getBounds(), { padding: [12, 12], animate: !poprve });
|
||||||
|
} else if (poprve && geojson.getLayers().length) {
|
||||||
map.fitBounds(geojson.getBounds(), { padding: [12, 12], animate: false });
|
map.fitBounds(geojson.getBounds(), { padding: [12, 12], animate: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function nastavRezim(novy) {
|
function nastavRezim(novy) {
|
||||||
if (!prihlaseny || (novy !== 'stari' && novy !== 'nedokoncene')) {
|
if (!prihlaseny || (novy !== 'stari' && novy !== 'nedokoncene' && novy !== 'sbor')) {
|
||||||
novy = 'obvody';
|
novy = 'obvody';
|
||||||
}
|
}
|
||||||
if (novy === rezim) {
|
if (novy === rezim) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue