Переработаны роутеры приложения
Переписано APi WebSocket для работы с новыми роутерами
This commit is contained in:
136
web/lib/pages/territory/constructor/index.html
Normal file
136
web/lib/pages/territory/constructor/index.html
Normal file
@@ -0,0 +1,136 @@
|
||||
<div class="page-constructor">
|
||||
<div id="part-1" class="part_block">
|
||||
<h1>
|
||||
<span>Крок 1.</span> Інформація про будинок, територію, точки на карті
|
||||
</h1>
|
||||
|
||||
<div id="info-type">
|
||||
<div class="tabs">
|
||||
<input
|
||||
type="radio"
|
||||
id="info-type-house"
|
||||
value="house"
|
||||
name="info-type"
|
||||
checked
|
||||
/>
|
||||
<label class="tab" for="info-type-house">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 14.5 6 A 1.50015 1.50015 0 0 0 13 7.5 L 13 25 L 7.5 25 A 1.50015 1.50015 0 0 0 6 26.5 L 6 42.5 A 1.50015 1.50015 0 1 0 9 42.5 L 9 28 L 14.253906 28 A 1.50015 1.50015 0 0 0 14.740234 28 L 19 28 L 19 42.5 A 1.50015 1.50015 0 1 0 22 42.5 L 22 26.746094 A 1.50015 1.50015 0 0 0 22 26.259766 L 22 22 L 33.253906 22 A 1.50015 1.50015 0 0 0 33.740234 22 L 39 22 L 39 42.5 A 1.50015 1.50015 0 1 0 42 42.5 L 42 20.5 A 1.50015 1.50015 0 0 0 40.5 19 L 35 19 L 35 7.5 A 1.50015 1.50015 0 0 0 33.5 6 L 14.5 6 z M 16 9 L 32 9 L 32 19 L 20.5 19 A 1.50015 1.50015 0 0 0 19 20.5 L 19 25 L 16 25 L 16 9 z M 20 12 C 19.448 12 19 12.448 19 13 L 19 15 C 19 15.552 19.448 16 20 16 L 22 16 C 22.552 16 23 15.552 23 15 L 23 13 C 23 12.448 22.552 12 22 12 L 20 12 z M 26 12 C 25.448 12 25 12.448 25 13 L 25 15 C 25 15.552 25.448 16 26 16 L 28 16 C 28.552 16 29 15.552 29 15 L 29 13 C 29 12.448 28.552 12 28 12 L 26 12 z M 26 25 C 25.448 25 25 25.448 25 26 L 25 28 C 25 28.552 25.448 29 26 29 L 28 29 C 28.552 29 29 28.552 29 28 L 29 26 C 29 25.448 28.552 25 28 25 L 26 25 z M 33 25 C 32.448 25 32 25.448 32 26 L 32 28 C 32 28.552 32.448 29 33 29 L 35 29 C 35.552 29 36 28.552 36 28 L 36 26 C 36 25.448 35.552 25 35 25 L 33 25 z M 13 31 C 12.448 31 12 31.448 12 32 L 12 34 C 12 34.552 12.448 35 13 35 L 15 35 C 15.552 35 16 34.552 16 34 L 16 32 C 16 31.448 15.552 31 15 31 L 13 31 z M 26 31 C 25.448 31 25 31.448 25 32 L 25 34 C 25 34.552 25.448 35 26 35 L 28 35 C 28.552 35 29 34.552 29 34 L 29 32 C 29 31.448 28.552 31 28 31 L 26 31 z M 33 31 C 32.448 31 32 31.448 32 32 L 32 34 C 32 34.552 32.448 35 33 35 L 35 35 C 35.552 35 36 34.552 36 34 L 36 32 C 36 31.448 35.552 31 35 31 L 33 31 z M 13 37 C 12.448 37 12 37.448 12 38 L 12 40 C 12 40.552 12.448 41 13 41 L 15 41 C 15.552 41 16 40.552 16 40 L 16 38 C 16 37.448 15.552 37 15 37 L 13 37 z M 26 37 C 25.448 37 25 37.448 25 38 L 25 40 C 25 40.552 25.448 41 26 41 L 28 41 C 28.552 41 29 40.552 29 40 L 29 38 C 29 37.448 28.552 37 28 37 L 26 37 z M 33 37 C 32.448 37 32 37.448 32 38 L 32 40 C 32 40.552 32.448 41 33 41 L 35 41 C 35.552 41 36 40.552 36 40 L 36 38 C 36 37.448 35.552 37 35 37 L 33 37 z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Багатоквартирний будинок</span>
|
||||
</label>
|
||||
|
||||
<input
|
||||
type="radio"
|
||||
id="info-type-homestead"
|
||||
value="homestead"
|
||||
name="info-type"
|
||||
/>
|
||||
<label class="tab" for="info-type-homestead">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 24 5.015625 C 22.851301 5.015625 21.70304 5.3892757 20.753906 6.1367188 A 1.50015 1.50015 0 0 0 20.751953 6.1367188 L 8.859375 15.509766 C 7.0558128 16.931133 6 19.102989 6 21.400391 L 6 39.488281 C 6 41.403236 7.5850452 42.988281 9.5 42.988281 L 38.5 42.988281 C 40.414955 42.988281 42 41.403236 42 39.488281 L 42 21.400391 C 42 19.102989 40.944187 16.931133 39.140625 15.509766 L 39 15.396484 L 39 7.5 A 1.50015 1.50015 0 0 0 37.5 6 L 32.5 6 A 1.50015 1.50015 0 0 0 31 7.5 L 31 9.09375 L 27.246094 6.1367188 C 26.29696 5.3892758 25.148699 5.015625 24 5.015625 z M 24 8.0078125 C 24.489801 8.0078125 24.979759 8.1705836 25.390625 8.4941406 L 31.572266 13.363281 A 1.50015 1.50015 0 0 0 34 12.185547 L 34 9 L 36 9 L 36 16.125 A 1.50015 1.50015 0 0 0 36.572266 17.302734 L 37.285156 17.865234 C 38.369594 18.719867 39 20.019792 39 21.400391 L 39 39.488281 C 39 39.783326 38.795045 39.988281 38.5 39.988281 L 9.5 39.988281 C 9.2049548 39.988281 9 39.783326 9 39.488281 L 9 21.400391 C 9 20.019792 9.6304058 18.719867 10.714844 17.865234 L 22.609375 8.4941406 C 23.020241 8.1705836 23.510199 8.0078125 24 8.0078125 z M 14.5 23.988281 A 1.50015 1.50015 0 0 0 13 25.488281 L 13 33.488281 A 1.50015 1.50015 0 0 0 14.5 34.988281 L 20.5 34.988281 A 1.50015 1.50015 0 0 0 22 33.488281 L 22 25.488281 A 1.50015 1.50015 0 0 0 20.5 23.988281 L 14.5 23.988281 z M 27.5 23.988281 A 1.50015 1.50015 0 0 0 26 25.488281 L 26 33.488281 A 1.50015 1.50015 0 0 0 27.5 34.988281 L 33.5 34.988281 A 1.50015 1.50015 0 0 0 35 33.488281 L 35 25.488281 A 1.50015 1.50015 0 0 0 33.5 23.988281 L 27.5 23.988281 z M 16 26.988281 L 19 26.988281 L 19 31.988281 L 16 31.988281 L 16 26.988281 z M 29 26.988281 L 32 26.988281 L 32 31.988281 L 29 31.988281 L 29 26.988281 z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Житловий район</span>
|
||||
</label>
|
||||
|
||||
<input
|
||||
type="radio"
|
||||
id="info-type-points"
|
||||
value="points"
|
||||
name="info-type"
|
||||
/>
|
||||
<label class="tab" for="info-type-points">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 24 4 C 16.285455 4 10 10.285455 10 18 C 10 21.46372 11.272608 24.643548 13.359375 27.085938 L 13.359375 27.087891 L 13.361328 27.087891 C 13.361328 27.087891 19.149094 33.866566 21.298828 35.917969 C 22.798087 37.348278 25.199464 37.347492 26.699219 35.917969 C 29.129083 33.600994 34.636721 27.090553 34.640625 27.085938 L 34.642578 27.082031 C 36.728766 24.639939 38 21.462159 38 18 C 38 10.285455 31.714545 4 24 4 z M 24 7 C 30.093455 7 35 11.906545 35 18 C 35 20.73228 34.005417 23.211194 32.359375 25.136719 L 32.359375 25.138672 L 32.357422 25.138672 C 32.357422 25.138672 26.632181 31.83589 24.628906 33.746094 C 24.258577 34.099392 23.73947 34.099392 23.369141 33.746094 C 21.715477 32.16807 15.643092 25.141834 15.638672 25.136719 L 15.636719 25.132812 C 13.99327 23.20762 13 20.730712 13 18 C 13 11.906545 17.906545 7 24 7 z M 24 12 C 22.125 12 20.528815 12.757133 19.503906 13.910156 C 18.478997 15.063179 18 16.541667 18 18 C 18 19.458333 18.478997 20.936821 19.503906 22.089844 C 20.528815 23.242867 22.125 24 24 24 C 25.875 24 27.471185 23.242867 28.496094 22.089844 C 29.521003 20.936821 30 19.458333 30 18 C 30 16.541667 29.521003 15.063179 28.496094 13.910156 C 27.471185 12.757133 25.875 12 24 12 z M 24 15 C 25.124999 15 25.778816 15.367867 26.253906 15.902344 C 26.728997 16.436821 27 17.208333 27 18 C 27 18.791667 26.728997 19.563179 26.253906 20.097656 C 25.778816 20.632133 25.124999 21 24 21 C 22.875001 21 22.221184 20.632133 21.746094 20.097656 C 21.271003 19.563179 21 18.791667 21 18 C 21 17.208333 21.271003 16.436821 21.746094 15.902344 C 22.221184 15.367867 22.875001 15 24 15 z M 12.771484 29.441406 C 8.2264844 30.754406 5 32.953 5 36 C 5 41.252 14.558 44 24 44 C 33.442 44 43 41.252 43 36 C 43 32.954 39.775422 30.757359 35.232422 29.443359 C 34.654422 30.099359 33.863187 30.993844 32.992188 31.964844 C 37.418188 33.005844 40 34.691 40 36 C 40 38.039 33.767 41 24 41 C 14.233 41 8 38.039 8 36 C 8 34.69 10.586531 33.001938 15.019531 31.960938 C 14.152531 30.995938 13.355484 30.100406 12.771484 29.441406 z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Точки на карті</span>
|
||||
</label>
|
||||
<span class="glider"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="info-form">
|
||||
<div>
|
||||
<label for="info-title">Назва вулиці</label>
|
||||
<input
|
||||
type="text"
|
||||
id="info-title"
|
||||
name="address"
|
||||
required
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="info-number">Номер будинку / частини</label>
|
||||
<input type="text" id="info-number" name="number" required value="" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="info-settlement">Місто</label>
|
||||
<input
|
||||
type="text"
|
||||
id="info-settlement"
|
||||
name="settlement"
|
||||
required
|
||||
value="Тернопіль"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button type="submit" id="part-1-button">Далі</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="part-2" class="part_block" style="display: none">
|
||||
<h1 id="part-2-title"><span>Крок 2.</span> Створення будинку / ділянки</h1>
|
||||
|
||||
<div class="osm-info">
|
||||
<div>
|
||||
<label for="info-settlement-title">OSM iD</label>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="123, 345, 678"
|
||||
onchange="Territory_constructor.osm.autoPoligon(this.value)"
|
||||
/>
|
||||
<a
|
||||
href="https://www.openstreetmap.org/#map=19/49.561725/25.604458"
|
||||
target="_blank"
|
||||
title="Де знайти OSM iD ?"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 48 48"
|
||||
width="100px"
|
||||
height="100px"
|
||||
>
|
||||
<path
|
||||
d="M 24 4 C 12.972066 4 4 12.972074 4 24 C 4 35.027926 12.972066 44 24 44 C 35.027934 44 44 35.027926 44 24 C 44 12.972074 35.027934 4 24 4 z M 24 7 C 33.406615 7 41 14.593391 41 24 C 41 33.406609 33.406615 41 24 41 C 14.593385 41 7 33.406609 7 24 C 7 14.593391 14.593385 7 24 7 z M 24 14 A 2 2 0 0 0 24 18 A 2 2 0 0 0 24 14 z M 23.976562 20.978516 A 1.50015 1.50015 0 0 0 22.5 22.5 L 22.5 33.5 A 1.50015 1.50015 0 1 0 25.5 33.5 L 25.5 22.5 A 1.50015 1.50015 0 0 0 23.976562 20.978516 z"
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<span>або</span>
|
||||
<button onclick="Territory_constructor.osm.newPoligon()">Обрати на карті</button>
|
||||
</div>
|
||||
|
||||
<div class="block-map">
|
||||
<div id="map"></div>
|
||||
</div>
|
||||
|
||||
<button type="button" id="part-2-button">Далі</button>
|
||||
</div>
|
||||
|
||||
<div id="part-3" class="part_block" style="display: none">
|
||||
<h1 id="part-3-title"><span>Крок 3.</span> Створення квартир</h1>
|
||||
|
||||
<button type="button" id="part-3-button">Зберегти</button>
|
||||
</div>
|
||||
</div>
|
||||
909
web/lib/pages/territory/constructor/script.js
Normal file
909
web/lib/pages/territory/constructor/script.js
Normal file
@@ -0,0 +1,909 @@
|
||||
let map, houseGroup, homesteadGroup, buildingGroup, pointsGroup;
|
||||
let numApartments = 1;
|
||||
let mode = '';
|
||||
|
||||
|
||||
const Territory_constructor = {
|
||||
info: {},
|
||||
async init() {
|
||||
let html = await fetch('/lib/pages/territory/constructor/index.html').then((response) => response.text());
|
||||
app.innerHTML = html;
|
||||
|
||||
map = "";
|
||||
houseGroup = "";
|
||||
homesteadGroup = "";
|
||||
buildingGroup = "";
|
||||
pointsGroup = "";
|
||||
numApartments = 1;
|
||||
|
||||
this.info = {
|
||||
type: 'house',
|
||||
points: [],
|
||||
points_number: [],
|
||||
geo: {},
|
||||
osm_id: [],
|
||||
zoom: 17,
|
||||
title: null,
|
||||
number: null,
|
||||
settlement: null
|
||||
}
|
||||
|
||||
const infoTypeInputs = document.querySelectorAll('input[name="info-type"]');
|
||||
const infoForm = document.getElementById('info-form');
|
||||
|
||||
const infoLabels = {
|
||||
points: {
|
||||
title: "Назва",
|
||||
number: "Номер",
|
||||
settlement: "Місто",
|
||||
init: () => Territory_constructor.points.init(),
|
||||
next: () => Territory_constructor.points.next(),
|
||||
save: () => Territory_constructor.points.save()
|
||||
},
|
||||
homestead: {
|
||||
title: "Назва району / села",
|
||||
number: "Номер району",
|
||||
settlement: "Місто",
|
||||
init: () => Territory_constructor.homestead.init(),
|
||||
next: () => Territory_constructor.homestead.next(),
|
||||
save: () => Territory_constructor.homestead.save()
|
||||
},
|
||||
house: {
|
||||
title: "Назва вулиці",
|
||||
number: "Номер будинку",
|
||||
settlement: "Місто",
|
||||
init: () => Territory_constructor.house.init(),
|
||||
next: () => Territory_constructor.house.next(),
|
||||
save: () => Territory_constructor.house.save()
|
||||
}
|
||||
};
|
||||
|
||||
let currentInit = infoLabels['house'].init;
|
||||
let currentNext = infoLabels['house'].next;
|
||||
let currentSave = infoLabels['house'].save;
|
||||
|
||||
function renderInfoForm(type) {
|
||||
const labels = infoLabels[type];
|
||||
currentInit = labels.init;
|
||||
currentNext = labels.next;
|
||||
currentSave = labels.save;
|
||||
|
||||
infoForm.innerHTML = `
|
||||
<div>
|
||||
<label for="info-title">${labels.title}</label>
|
||||
<input type="text" id="info-title" name="address" required value=""/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="info-number">${labels.number}</label>
|
||||
<input type="text" id="info-number" name="number" required value=""/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="info-settlementv">${labels.settlement}</label>
|
||||
<input type="text" id="info-settlement" name="settlement" required value="Тернопіль"/>
|
||||
</div>
|
||||
|
||||
<button type="submit" id="part-1-button">Далі</button>
|
||||
`;
|
||||
}
|
||||
|
||||
// Обработчик submit формы
|
||||
infoForm.addEventListener('submit', (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
document.getElementById('part-1-button').style.display = "none";
|
||||
|
||||
['title', 'number', 'settlement'].forEach(key => {
|
||||
Territory_constructor.info[key] = document.getElementById(`info-${key}`).value;
|
||||
});
|
||||
|
||||
if (currentInit) currentInit();
|
||||
});
|
||||
|
||||
// Слушатели радиокнопок
|
||||
infoTypeInputs.forEach(radio => {
|
||||
radio.addEventListener('change', event => {
|
||||
const value = event.target.value;
|
||||
|
||||
const part_2 = document.getElementById('part-2');
|
||||
const part_2_button = document.getElementById('part-2-button');
|
||||
part_2.style.display = "none";
|
||||
part_2_button.style.display = "";
|
||||
|
||||
const part_3 = document.getElementById('part-3');
|
||||
part_3.style.display = "none";
|
||||
|
||||
renderInfoForm(value);
|
||||
console.log(`Вибрано: ${value}`);
|
||||
|
||||
this.info.type = value;
|
||||
this.info.osm_id = null;
|
||||
this.info.geo = {};
|
||||
this.info.points_number = [];
|
||||
this.info.points = [];
|
||||
this.house.apartments.quantity = 0;
|
||||
this.house.apartments.list = [];
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('part-2-button').addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
document.getElementById('part-2-button').style.display = "none";
|
||||
|
||||
if (currentNext) currentNext();
|
||||
});
|
||||
|
||||
document.getElementById('part-3-button').addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
// document.getElementById('part-3-button').style.display = "none";
|
||||
|
||||
if (currentSave) currentSave();
|
||||
});
|
||||
},
|
||||
|
||||
points: {
|
||||
init() {
|
||||
console.log('points');
|
||||
// const part_2 = document.getElementById('part-2');
|
||||
// const part_2_title = document.getElementById('part-2-title');
|
||||
// part_2_title.innerHTML = `<span>Крок 2.</span> Створення точок на карті`;
|
||||
// part_2.style.display = "";
|
||||
|
||||
},
|
||||
|
||||
next() {
|
||||
console.log('points next');
|
||||
|
||||
},
|
||||
|
||||
save() {
|
||||
console.log('points next save');
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
homestead: {
|
||||
init() {
|
||||
console.log('homestead');
|
||||
const part_2 = document.getElementById('part-2');
|
||||
const part_2_title = document.getElementById('part-2-title');
|
||||
part_2_title.innerHTML = `<span>Крок 2.</span> Створення ділянки`;
|
||||
part_2.style.display = "";
|
||||
|
||||
Territory_constructor.osm.init();
|
||||
},
|
||||
|
||||
next() {
|
||||
console.log('homestead next');
|
||||
const part_3 = document.getElementById('part-3');
|
||||
const title = part_3.querySelector('h1');
|
||||
const button = part_3.querySelector('#part-3-button');
|
||||
part_3.innerHTML = '';
|
||||
|
||||
title.innerHTML = `<span>Крок 3.</span> Створення будинків`;
|
||||
|
||||
part_3.appendChild(title);
|
||||
part_3.innerHTML += `
|
||||
<div class="info">
|
||||
<p>*Натисніть кнопку нижче, а потім клацайте на карті, щоб додати будинки. Після цього натисніть "Зберегти".</p>
|
||||
<p>*Щоб видалити будинок, клацніть на ньому та у спливаючому вікні оберіть "Видалити".</p>
|
||||
<br />
|
||||
<button onclick="Territory_constructor.homestead.building.newHouse(this)">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path d="M 22.828125 3 C 22.316375 3 21.804562 3.1954375 21.414062 3.5859375 L 19 6 L 24 11 L 26.414062 8.5859375 C 27.195062 7.8049375 27.195062 6.5388125 26.414062 5.7578125 L 24.242188 3.5859375 C 23.851688 3.1954375 23.339875 3 22.828125 3 z M 17 8 L 5.2597656 19.740234 C 5.2597656 19.740234 6.1775313 19.658 6.5195312 20 C 6.8615312 20.342 6.58 22.58 7 23 C 7.42 23.42 9.6438906 23.124359 9.9628906 23.443359 C 10.281891 23.762359 10.259766 24.740234 10.259766 24.740234 L 22 13 L 17 8 z M 4 23 L 3.0566406 25.671875 A 1 1 0 0 0 3 26 A 1 1 0 0 0 4 27 A 1 1 0 0 0 4.328125 26.943359 A 1 1 0 0 0 4.3378906 26.939453 L 4.3632812 26.931641 A 1 1 0 0 0 4.3691406 26.927734 L 7 26 L 5.5 24.5 L 4 23 z"></path></svg>
|
||||
<span>Додати будинок</span>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
part_3.appendChild(button);
|
||||
part_3.style.display = "";
|
||||
|
||||
this.building.init();
|
||||
|
||||
},
|
||||
|
||||
async save() {
|
||||
Territory_constructor.info.buildings = Territory_constructor.homestead.building.list;
|
||||
|
||||
console.log(Territory_constructor.info);
|
||||
|
||||
Territory_constructor.save();
|
||||
},
|
||||
|
||||
building: {
|
||||
list: [], editing: false,
|
||||
async init() {
|
||||
this.editing = false;
|
||||
setLeafletCursor('pointer');
|
||||
|
||||
// Обробник кліку на карту
|
||||
homesteadGroup.on('click', e => {
|
||||
console.log(this.editing);
|
||||
|
||||
if (e.layer instanceof L.Marker || !this.editing) return;
|
||||
|
||||
const { lat, lng } = e.latlng;
|
||||
console.log(`Координати: ${lat.toFixed(5)}, ${lng.toFixed(5)}`);
|
||||
|
||||
setLeafletCursor('progress');
|
||||
this.editing = false;
|
||||
|
||||
this.addBuilding({ geo: e.latlng, title: this.list.length + 1 });
|
||||
});
|
||||
},
|
||||
|
||||
async addBuilding({ geo, title }) {
|
||||
this.list.push({
|
||||
title: title,
|
||||
geo: geo
|
||||
});
|
||||
|
||||
// Додаємо маркер на карту
|
||||
const redDot = L.divIcon({
|
||||
className: "leaflet_drop",
|
||||
html: `<div id="redDot_${this.list.length}"></div>`,
|
||||
iconSize: [16, 16],
|
||||
iconAnchor: [8, 8]
|
||||
});
|
||||
|
||||
const marker = L.marker(geo, { icon: redDot }).addTo(buildingGroup);
|
||||
marker.bindPopup(`
|
||||
Будинок: ${this.list.length}<br>
|
||||
Координати: ${geo.lat.toFixed(5)}, ${geo.lng.toFixed(5)}<br>
|
||||
<button class="map_dell" onclick="Territory_constructor.homestead.building.delleteBuilding({id: ${this.list.length}})" type="button">Видалити</button>
|
||||
`);
|
||||
|
||||
setLeafletCursor('crosshair');
|
||||
this.editing = true;
|
||||
},
|
||||
|
||||
async delleteBuilding({ id }) {
|
||||
const el = document.getElementById(`redDot_${id}`);
|
||||
if (el) el.remove();
|
||||
|
||||
this.list = this.list.filter(item => item.title !== id);
|
||||
|
||||
const block = document.getElementById(`Building_${id}`);
|
||||
if (block) block.remove();
|
||||
|
||||
houseGroup.eachLayer(layer => {
|
||||
if (layer instanceof L.Marker && layer.getPopup()?.getContent().includes(`Будинок: ${id}`)) {
|
||||
houseGroup.removeLayer(layer);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
newHouse(element) {
|
||||
const btn = element;
|
||||
this.editing = !this.editing;
|
||||
setLeafletCursor(this.editing ? 'crosshair' : 'pointer');
|
||||
btn.innerHTML = this.editing
|
||||
? `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"> <path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z" ></path> </svg><span>Завершити додавання</span>`
|
||||
: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"> <path d="M 22.828125 3 C 22.316375 3 21.804562 3.1954375 21.414062 3.5859375 L 19 6 L 24 11 L 26.414062 8.5859375 C 27.195062 7.8049375 27.195062 6.5388125 26.414062 5.7578125 L 24.242188 3.5859375 C 23.851688 3.1954375 23.339875 3 22.828125 3 z M 17 8 L 5.2597656 19.740234 C 5.2597656 19.740234 6.1775313 19.658 6.5195312 20 C 6.8615312 20.342 6.58 22.58 7 23 C 7.42 23.42 9.6438906 23.124359 9.9628906 23.443359 C 10.281891 23.762359 10.259766 24.740234 10.259766 24.740234 L 22 13 L 17 8 z M 4 23 L 3.0566406 25.671875 A 1 1 0 0 0 3 26 A 1 1 0 0 0 4 27 A 1 1 0 0 0 4.328125 26.943359 A 1 1 0 0 0 4.3378906 26.939453 L 4.3632812 26.931641 A 1 1 0 0 0 4.3691406 26.927734 L 7 26 L 5.5 24.5 L 4 23 z" ></path> </svg><span>Додати будинок</span>`;
|
||||
if (this.editing) alert("Натискаючи на карту будуть створюватись нові точки (будинки)");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
house: {
|
||||
init() {
|
||||
console.log('house');
|
||||
const part_2 = document.getElementById('part-2');
|
||||
const part_2_title = document.getElementById('part-2-title');
|
||||
part_2_title.innerHTML = `<span>Крок 2.</span> Конструктор будинків`;
|
||||
part_2.style.display = "";
|
||||
|
||||
Territory_constructor.osm.init();
|
||||
},
|
||||
|
||||
next() {
|
||||
console.log('house next');
|
||||
const part_3 = document.getElementById('part-3');
|
||||
const title = part_3.querySelector('h1');
|
||||
const button = part_3.querySelector('#part-3-button');
|
||||
part_3.innerHTML = '';
|
||||
|
||||
title.innerHTML = `<span>Крок 3.</span> Конструктор квартир`;
|
||||
|
||||
part_3.appendChild(title);
|
||||
part_3.innerHTML += `<input onchange="Territory_constructor.house.apartments.editQuantity(this.value)" type="number" value="1" id="next-apartment-title" title="Авто-номер наступної квартири">`
|
||||
part_3.appendChild(button);
|
||||
part_3.style.display = "";
|
||||
|
||||
this.apartments.init();
|
||||
|
||||
},
|
||||
|
||||
async save() {
|
||||
console.log('house next save');
|
||||
Territory_constructor.info.entrances = this.apartments.list.map((entrance, entranceIndex) => {
|
||||
let apartments = [];
|
||||
let apartmentCounter = 0;
|
||||
|
||||
entrance.list.forEach((floor, floorIndex) => {
|
||||
floor.forEach(apartment => {
|
||||
apartments.push({
|
||||
title: apartment.title,
|
||||
apartment_number: apartmentCounter++,
|
||||
floors_number: floorIndex + 1
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
title: entrance.title,
|
||||
entrance_number: entranceIndex,
|
||||
apartments
|
||||
};
|
||||
});
|
||||
|
||||
Territory_constructor.save();
|
||||
},
|
||||
|
||||
apartments: {
|
||||
quantity: 0,
|
||||
list: [],
|
||||
|
||||
init() {
|
||||
const part_3 = document.getElementById("part-3");
|
||||
const part_3_Button = part_3.querySelector("#part-3-button");
|
||||
|
||||
this.quantity++;
|
||||
const newEntrance = {
|
||||
title: `Під'їзд ${this.list.length + 1}`,
|
||||
list: [[{ title: this.quantity }]]
|
||||
};
|
||||
this.list.push(newEntrance);
|
||||
|
||||
const eIndex = this.list.length - 1;
|
||||
const floorIndex = 0;
|
||||
const apartmentIndex = 0;
|
||||
|
||||
const houseDiv = this.createHouse(eIndex);
|
||||
const entranceDiv = this.createEntrance(eIndex);
|
||||
const floorDiv = this.createFloor(eIndex, floorIndex);
|
||||
const apartmentDiv = this.createApartment(eIndex, floorIndex, apartmentIndex, this.quantity);
|
||||
|
||||
floorDiv.insertBefore(apartmentDiv, floorDiv.querySelector(".floor-info"));
|
||||
entranceDiv.appendChild(floorDiv);
|
||||
houseDiv.insertBefore(entranceDiv, houseDiv.querySelector(".entrance-button"));
|
||||
part_3.insertBefore(houseDiv, part_3_Button);
|
||||
},
|
||||
|
||||
createApartment(entrance, floor, apartment, value) {
|
||||
const div = document.createElement("div");
|
||||
div.className = "apartment";
|
||||
div.id = `apartment-${entrance}-${floor}-${apartment}`;
|
||||
div.innerHTML = `
|
||||
<input onchange="Territory_constructor.house.apartments.editApartment(${entrance}, ${floor}, ${apartment}, this.value)" type="text" value="${value}">
|
||||
<button onclick="Territory_constructor.house.apartments.deleteApartment(${entrance}, ${floor}, ${apartment})" title="Видалити квартиру" type="button">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>
|
||||
</button>
|
||||
`;
|
||||
return div;
|
||||
},
|
||||
|
||||
createFloor(entrance, floor) {
|
||||
const div = document.createElement("div");
|
||||
div.className = "floor";
|
||||
div.id = `floor-${entrance}-${floor}`;
|
||||
div.innerHTML = `
|
||||
<div class="floor-info">
|
||||
<h2>Поверх ${floor + 1}</h2>
|
||||
<button onclick="Territory_constructor.house.apartments.addApartment(${entrance}, ${floor})" title="Додати квартиру" type="button">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>
|
||||
</button>
|
||||
</div>`;
|
||||
return div;
|
||||
},
|
||||
|
||||
createEntrance(entrance) {
|
||||
const div = document.createElement("div");
|
||||
div.className = "entrance";
|
||||
div.id = `entrance-${entrance}`;
|
||||
div.innerHTML = `
|
||||
<div class="entrance-info">
|
||||
<input onchange="Territory_constructor.house.apartments.editEntrance(${entrance}, this.value)" type="text" value="Під'їзд ${entrance + 1}">
|
||||
<button onclick="Territory_constructor.house.apartments.addFloors(${entrance})" title="Додати поверх" type="button">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>
|
||||
</button>
|
||||
</div>`;
|
||||
return div;
|
||||
},
|
||||
|
||||
createHouse() {
|
||||
const div = document.createElement("div");
|
||||
div.id = `house`;
|
||||
div.innerHTML = `
|
||||
<button class="entrance-button" onclick="Territory_constructor.house.apartments.addEntrance()" title="Додати під'їзд" type="button">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"> <path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>
|
||||
</button>`;
|
||||
return div;
|
||||
},
|
||||
|
||||
addEntrance() {
|
||||
const blockHouse = document.getElementById("house");
|
||||
const houseButton = blockHouse.querySelector(".entrance-button");
|
||||
|
||||
this.editQuantity(this.quantity + 1);
|
||||
const newEntrance = {
|
||||
title: `Під'їзд ${this.list.length + 1}`,
|
||||
list: [[{ title: this.quantity }]]
|
||||
};
|
||||
this.list.push(newEntrance);
|
||||
|
||||
const eIndex = this.list.length - 1;
|
||||
const floorIndex = 0;
|
||||
const apartmentIndex = 0;
|
||||
|
||||
const entranceDiv = this.createEntrance(eIndex);
|
||||
const floorDiv = this.createFloor(eIndex, floorIndex);
|
||||
const apartmentDiv = this.createApartment(eIndex, floorIndex, apartmentIndex, this.quantity);
|
||||
|
||||
floorDiv.insertBefore(apartmentDiv, floorDiv.querySelector(".floor-info"));
|
||||
entranceDiv.appendChild(floorDiv);
|
||||
blockHouse.insertBefore(entranceDiv, houseButton);
|
||||
},
|
||||
|
||||
editEntrance(entrance, value) {
|
||||
this.list[entrance].title = value;
|
||||
},
|
||||
|
||||
addFloors(entrance) {
|
||||
const entranceBlock = document.getElementById(`entrance-${entrance}`);
|
||||
const entranceInfo = entranceBlock.querySelector(".entrance-info");
|
||||
|
||||
this.editQuantity(this.quantity + 1);
|
||||
this.list[entrance].list.push([{ title: this.quantity }]);
|
||||
const fIndex = this.list[entrance].list.length - 1;
|
||||
|
||||
const floorDiv = this.createFloor(entrance, fIndex);
|
||||
const aptDiv = this.createApartment(entrance, fIndex, 0, this.quantity);
|
||||
|
||||
floorDiv.insertBefore(aptDiv, floorDiv.querySelector(".floor-info"));
|
||||
entranceInfo.after(floorDiv);
|
||||
},
|
||||
|
||||
addApartment(entrance, floor) {
|
||||
const blockFloor = document.getElementById(`floor-${entrance}-${floor}`);
|
||||
const floorInfo = blockFloor.querySelector(".floor-info");
|
||||
|
||||
this.editQuantity(this.quantity + 1);
|
||||
this.list[entrance].list[floor].push({ title: this.quantity });
|
||||
const aIndex = this.list[entrance].list[floor].length - 1;
|
||||
|
||||
const aptDiv = this.createApartment(entrance, floor, aIndex, this.quantity);
|
||||
blockFloor.insertBefore(aptDiv, floorInfo);
|
||||
},
|
||||
|
||||
editApartment(entrance, floor, apartment, value) {
|
||||
this.list[entrance].list[floor][apartment].title = value;
|
||||
},
|
||||
|
||||
deleteApartment(entrance, floor, apartment) {
|
||||
this.list[entrance].list[floor].splice(apartment, 1);
|
||||
document.getElementById(`apartment-${entrance}-${floor}-${apartment}`)?.remove();
|
||||
|
||||
this.editQuantity(this.quantity - 1);
|
||||
},
|
||||
|
||||
editQuantity(value) {
|
||||
const next_apartment_title = document.getElementById('next-apartment-title');
|
||||
next_apartment_title.style.display = "";
|
||||
next_apartment_title.value = value;
|
||||
|
||||
this.quantity = Number(value);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
osm: {
|
||||
init() {
|
||||
const center = { lat: 49.5629016, lng: 25.6145625 };
|
||||
const zoom = 19;
|
||||
|
||||
const googleHybrid = L.tileLayer('http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}', {
|
||||
subdomains: ['mt0', 'mt1', 'mt2', 'mt3']
|
||||
});
|
||||
const osm = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
|
||||
const mytile = L.tileLayer('https://sheep-service.com/map/{z}/{x}/{y}.webp', {
|
||||
maxZoom: 20, minZoom: 15, tms: true
|
||||
});
|
||||
|
||||
if (!map) {
|
||||
houseGroup = new L.FeatureGroup();
|
||||
homesteadGroup = new L.FeatureGroup();
|
||||
buildingGroup = new L.FeatureGroup();
|
||||
pointsGroup = new L.FeatureGroup();
|
||||
|
||||
map = L.map('map', {
|
||||
renderer: L.canvas(), center, zoom,
|
||||
layers: [googleHybrid, osm, mytile, houseGroup, homesteadGroup, buildingGroup, pointsGroup],
|
||||
zoomControl: false
|
||||
});
|
||||
|
||||
|
||||
L.control.layers(
|
||||
{ "Google Hybrid": googleHybrid, "OpenStreetMap": osm, "Territory Map": mytile },
|
||||
{
|
||||
"Багатоповерхові будинки": houseGroup,
|
||||
"Житлові райони": homesteadGroup,
|
||||
"Приватні будинки": buildingGroup,
|
||||
"Точки на карті": pointsGroup
|
||||
},
|
||||
{ position: 'bottomright' }
|
||||
).addTo(map);
|
||||
|
||||
map.pm.addControls({
|
||||
position: 'bottomright',
|
||||
drawCircleMarker: false,
|
||||
drawPolyline: false,
|
||||
drawPolygon: false,
|
||||
drawRectangle: false,
|
||||
drawCircle: false,
|
||||
drawText: false,
|
||||
drawMarker: false,
|
||||
cutPolygon: false,
|
||||
tooltips: false,
|
||||
editMode: true,
|
||||
dragMode: true,
|
||||
});
|
||||
map.pm.toggleControls()
|
||||
|
||||
|
||||
// Событие после завершения рисования
|
||||
map.on('pm:create', e => {
|
||||
const layer = e.layer;
|
||||
|
||||
let LatLngs = layer.getLatLngs();
|
||||
LatLngs[0].push(LatLngs[0][0]);
|
||||
|
||||
Territory_constructor.info.points.push(LatLngs);
|
||||
Territory_constructor.info.points_number.push(this.center(layer.getLatLngs()));
|
||||
let geo = this.center(layer.getLatLngs());
|
||||
|
||||
const house = layer; // сохраняем именно слой
|
||||
|
||||
if (Territory_constructor.info.type === 'house') {
|
||||
houseGroup.addLayer(house);
|
||||
} else if (Territory_constructor.info.type === 'homestead') {
|
||||
homesteadGroup.addLayer(house);
|
||||
}
|
||||
|
||||
house.bindPopup(`
|
||||
Координати: ${geo.lat.toFixed(5)}, ${geo.lng.toFixed(5)}<br>
|
||||
<button class="map_dell" type="button">Видалити</button>
|
||||
`);
|
||||
|
||||
// при открытии popup вешаем обработчик удаления
|
||||
house.on('popupopen', (e) => {
|
||||
if (Territory_constructor.homestead.building.editing) {
|
||||
house.closePopup();
|
||||
return;
|
||||
}
|
||||
|
||||
const btn = e.popup.getElement().querySelector('.map_dell');
|
||||
if (btn) {
|
||||
btn.addEventListener('click', () => {
|
||||
Territory_constructor.osm.delete(house);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Territory_constructor.osm.autoZoom(Territory_constructor.info.points);
|
||||
});
|
||||
|
||||
map.pm.setLang("ua");
|
||||
}
|
||||
|
||||
houseGroup.clearLayers();
|
||||
homesteadGroup.clearLayers();
|
||||
buildingGroup.clearLayers();
|
||||
pointsGroup.clearLayers();
|
||||
},
|
||||
|
||||
newPoligon() {
|
||||
if (Territory_constructor.info.type === 'house') {
|
||||
map.pm.enableDraw('Polygon', {
|
||||
snappable: true,
|
||||
snapDistance: 20,
|
||||
layerGroup: houseGroup,
|
||||
templineStyle: {
|
||||
color: '#585858',
|
||||
radius: 500,
|
||||
fillOpacity: 0.4,
|
||||
dashArray: '5, 10',
|
||||
dashOffset: '20',
|
||||
},
|
||||
hintlineStyle: {
|
||||
color: '#C14D4D',
|
||||
dashArray: '5, 10'
|
||||
},
|
||||
pathOptions: {
|
||||
color: "#585858",
|
||||
fillColor: "#f2bd53",
|
||||
fillOpacity: 0.8
|
||||
}
|
||||
});
|
||||
} else if (Territory_constructor.info.type === 'homestead') {
|
||||
map.pm.enableDraw('Polygon', {
|
||||
snappable: true,
|
||||
snapDistance: 20,
|
||||
layerGroup: houseGroup,
|
||||
templineStyle: {
|
||||
color: '#585858',
|
||||
radius: 500,
|
||||
fillOpacity: 0.3,
|
||||
dashArray: '5, 10',
|
||||
dashOffset: '20',
|
||||
},
|
||||
hintlineStyle: {
|
||||
color: '#C14D4D',
|
||||
dashArray: '5, 10'
|
||||
},
|
||||
pathOptions: {
|
||||
color: "#f2bd53",
|
||||
fillColor: "#f2bd53",
|
||||
radius: 500,
|
||||
fillOpacity: 0.3,
|
||||
dashArray: '5, 10'
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async autoPoligon(IDs) {
|
||||
if (!IDs) return;
|
||||
|
||||
const ids_list = IDs.replace(/\s+/g, "").split(',');
|
||||
Territory_constructor.info.osm_id = ids_list;
|
||||
|
||||
houseGroup.clearLayers();
|
||||
homesteadGroup.clearLayers();
|
||||
|
||||
Territory_constructor.info.points = [];
|
||||
Territory_constructor.info.points_number = [];
|
||||
Territory_constructor.info.geo = {}
|
||||
|
||||
|
||||
// 1006306041, 1006306065
|
||||
|
||||
|
||||
for (let i = 0; i < ids_list.length; i++) {
|
||||
const element = await Territory_constructor.osm.getOSM(Territory_constructor.info.osm_id[i]);
|
||||
|
||||
// Преобразуем координаты в LatLng
|
||||
const LatLngs = [[]];
|
||||
element[0].forEach(feature => LatLngs[0].push({ lat: feature.lat, lng: feature.lng }));
|
||||
|
||||
// Замыкаем полигон
|
||||
if (LatLngs[0][0] && LatLngs[0][0] !== LatLngs[0][LatLngs[0].length - 1]) {
|
||||
LatLngs[0].push(LatLngs[0][0]);
|
||||
}
|
||||
|
||||
// Считаем центр
|
||||
const center = this.center(LatLngs);
|
||||
|
||||
// Сохраняем в points / points_number
|
||||
Territory_constructor.info.points.push(LatLngs);
|
||||
Territory_constructor.info.points_number.push(center);
|
||||
|
||||
// Создаем L.polygon
|
||||
const polyOptions = Territory_constructor.info.type === 'homestead'
|
||||
? { color: "#f2bd53", fillColor: "#f2bd53", fillOpacity: 0.4, dashArray: '5,10' }
|
||||
: { color: "#585858", fillColor: "#f2bd53", fillOpacity: 0.8 };
|
||||
|
||||
const house = L.polygon(LatLngs, polyOptions);
|
||||
|
||||
// Добавляем в нужную группу
|
||||
if (Territory_constructor.info.type === 'house') {
|
||||
houseGroup.addLayer(house);
|
||||
} else if (Territory_constructor.info.type === 'homestead') {
|
||||
homesteadGroup.addLayer(house);
|
||||
}
|
||||
|
||||
// Bind popup с кнопкой удаления
|
||||
house.bindPopup(`
|
||||
Координати: ${center.lat.toFixed(5)}, ${center.lng.toFixed(5)}<br>
|
||||
<button class="map_dell" type="button">Видалити</button>
|
||||
`);
|
||||
|
||||
house.on('popupopen', (e) => {
|
||||
if (Territory_constructor.homestead.building.editing) {
|
||||
house.closePopup();
|
||||
return;
|
||||
}
|
||||
|
||||
const btn = e.popup.getElement().querySelector('.map_dell');
|
||||
if (btn) {
|
||||
btn.addEventListener('click', () => {
|
||||
Territory_constructor.osm.delete(house);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Territory_constructor.osm.autoZoom(Territory_constructor.info.points);
|
||||
},
|
||||
|
||||
center(geo) {
|
||||
// Получаем координаты полигона Leaflet
|
||||
let latlngs = geo[0];
|
||||
|
||||
// Преобразуем в формат GeoJSON для Turf
|
||||
const coordinates = latlngs.map(ll => [ll.lng, ll.lat]);
|
||||
const polygonGeoJSON = {
|
||||
type: "Feature",
|
||||
geometry: {
|
||||
type: "Polygon",
|
||||
coordinates: [coordinates]
|
||||
}
|
||||
};
|
||||
|
||||
// Находим центроид
|
||||
const centroid = turf.centroid(polygonGeoJSON);
|
||||
|
||||
latlngs = { lat: centroid.geometry.coordinates[1], lng: centroid.geometry.coordinates[0] }
|
||||
|
||||
return latlngs;
|
||||
},
|
||||
|
||||
autoZoom(polygons) {
|
||||
if (!polygons || !polygons.length) return;
|
||||
|
||||
const allBounds = [];
|
||||
|
||||
polygons.forEach(polygon => {
|
||||
const ring = polygon[0];
|
||||
if (!ring || ring.length < 3) return;
|
||||
|
||||
const coords = ring.map(p => [p.lng, p.lat]);
|
||||
if (coords[0][0] !== coords[coords.length - 1][0] || coords[0][1] !== coords[coords.length - 1][1]) {
|
||||
coords.push(coords[0]);
|
||||
}
|
||||
|
||||
const polygonGeoJSON = turf.polygon([coords]);
|
||||
const bbox = turf.bbox(polygonGeoJSON);
|
||||
const bounds = L.latLngBounds(
|
||||
[bbox[1], bbox[0]],
|
||||
[bbox[3], bbox[2]]
|
||||
);
|
||||
|
||||
allBounds.push(bounds);
|
||||
});
|
||||
|
||||
if (!allBounds.length) return;
|
||||
|
||||
// Если один полигон, просто fitBounds на него
|
||||
if (allBounds.length === 1) {
|
||||
map.fitBounds(allBounds[0]);
|
||||
} else {
|
||||
// Несколько полигонов → объединяем bounds
|
||||
let finalBounds = allBounds[0];
|
||||
for (let i = 1; i < allBounds.length; i++) {
|
||||
finalBounds = finalBounds.extend(allBounds[i]);
|
||||
}
|
||||
map.fitBounds(finalBounds);
|
||||
}
|
||||
|
||||
|
||||
if (map.getZoom() > 18) map.setZoom(18);
|
||||
|
||||
setTimeout(() => {
|
||||
Territory_constructor.info.zoom = map.getZoom();
|
||||
Territory_constructor.info.geo = map.getCenter();
|
||||
}, 200)
|
||||
},
|
||||
|
||||
delete(house) {
|
||||
// убрать слой с карты
|
||||
if (Editor.info.type === 'house') {
|
||||
houseGroup.removeLayer(house);
|
||||
} else if (Editor.info.type === 'homestead') {
|
||||
homesteadGroup.removeLayer(house);
|
||||
}
|
||||
|
||||
// найти индекс полигона в points
|
||||
const target = house.getLatLngs()[0]; // вершины полигона
|
||||
|
||||
const index = Editor.info.points.findIndex((p) => {
|
||||
const copy = p.slice(); // делаем копию
|
||||
copy[0].pop(); // убираем последний элемент
|
||||
|
||||
if (isSamePolygon(p, target)) return true; // проверка как есть
|
||||
if (isSamePolygon(copy, target)) return true; // проверка без последнего
|
||||
return false;
|
||||
});
|
||||
|
||||
function isSamePolygon(a, b) {
|
||||
if (a.length !== b.length) return false;
|
||||
return a.every((pt, i) => pt.lat === b[i].lat && pt.lng === b[i].lng);
|
||||
}
|
||||
|
||||
|
||||
if (index) {
|
||||
// удалить из points и points_number по индексу
|
||||
Editor.info.points.splice(index, 1);
|
||||
Editor.info.points_number.splice(index, 1);
|
||||
}
|
||||
|
||||
Editor.osm.autoZoom(Editor.info.points);
|
||||
},
|
||||
|
||||
async getOSM(wayId) {
|
||||
const overpassUrl = `https://overpass-api.de/api/interpreter?data=[out:json];way(${wayId});(._;>;);out;`;
|
||||
|
||||
return await fetch(overpassUrl)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const nodes = new Map();
|
||||
|
||||
data.elements.forEach(el => {
|
||||
if (el.type === "node") {
|
||||
nodes.set(el.id, { lat: el.lat, lng: el.lon });
|
||||
}
|
||||
});
|
||||
|
||||
const way = data.elements.find(el => el.type === "way");
|
||||
if (way) {
|
||||
const coordinates = way.nodes.map(nodeId => nodes.get(nodeId));
|
||||
|
||||
return [coordinates];
|
||||
} else {
|
||||
console.error("Way не найден!");
|
||||
}
|
||||
})
|
||||
.catch(error => console.error("Ошибка запроса:", error));
|
||||
},
|
||||
},
|
||||
|
||||
async save() {
|
||||
const part_3_button = document.getElementById('part-3-button');
|
||||
|
||||
console.log(Territory_constructor.info);
|
||||
|
||||
setLeafletCursor('pointer');
|
||||
Territory_constructor.homestead.building.editing = false;
|
||||
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const URL = `${CONFIG.api}constructor`;
|
||||
await fetch(URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
body: JSON.stringify(Territory_constructor.info)
|
||||
})
|
||||
.then(response => {
|
||||
if (response.status == 200) {
|
||||
console.log({ 'setPack': 'ok' });
|
||||
part_3_button.innerText = "Запис додано";
|
||||
|
||||
return response.json()
|
||||
} else {
|
||||
console.log('err');
|
||||
part_3_button.innerText = "Помилка запису";
|
||||
|
||||
return
|
||||
}
|
||||
})
|
||||
.then(data => {
|
||||
console.log(data);
|
||||
|
||||
Territory.house.list = [];
|
||||
Territory.homestead.list = [];
|
||||
Router.navigate(`/territory/manager/${Territory_constructor.info.type}/${data.id}`);
|
||||
|
||||
setTimeout(() => {
|
||||
part_3_button.innerText = "Зберегти";
|
||||
}, 3000);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
part_3_button.innerText = "Помилка запису";
|
||||
})
|
||||
}
|
||||
}
|
||||
478
web/lib/pages/territory/constructor/style.css
Normal file
478
web/lib/pages/territory/constructor/style.css
Normal file
@@ -0,0 +1,478 @@
|
||||
.page-constructor {
|
||||
width: calc(100% - 40px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: 20px 20px 0 20px;
|
||||
}
|
||||
|
||||
.page-constructor>#part-1,
|
||||
.page-constructor>#part-2,
|
||||
.page-constructor>#part-3 {
|
||||
border-radius: 10px;
|
||||
width: calc(100% - 40px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
margin-bottom: 20px;
|
||||
background: var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
box-shadow: var(--shadow-l1);
|
||||
padding: 0 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>h1,
|
||||
.page-constructor>#part-2>h1,
|
||||
.page-constructor>#part-3>h1 {
|
||||
width: calc(100% - 40px);
|
||||
color: var(--ColorThemes3);
|
||||
border-radius: var(--border-radius);
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 300;
|
||||
padding: 20px 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>h1>span,
|
||||
.page-constructor>#part-2>h1>span,
|
||||
.page-constructor>#part-3>h1>span {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>#info-type {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>#info-type>.tabs {
|
||||
display: flex;
|
||||
position: relative;
|
||||
background-color: var(--ColorThemes0);
|
||||
padding: 4px;
|
||||
border-radius: 6px;
|
||||
width: calc(100% - 8px);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
|
||||
.page-constructor>#part-1>#info-type>.tabs>input[type="radio"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>#info-type>.tabs>.tab {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 40px;
|
||||
width: calc(100% / 3);
|
||||
cursor: pointer;
|
||||
padding: 0 15px;
|
||||
transition: 0.15s ease-in;
|
||||
color: var(--ColorThemes3);
|
||||
fill: var(--ColorThemes3);
|
||||
flex-direction: row;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>#info-type>.tabs>.tab>svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>#info-type>.tabs>.tab>span {
|
||||
margin-left: 6px;
|
||||
font-size: var(--FontSize1);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>#info-type>.tabs>input[type="radio"]:checked+label {
|
||||
color: var(--PrimaryColorText);
|
||||
fill: var(--PrimaryColorText);
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>#info-type>.tabs>.glider {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
height: 40px;
|
||||
width: calc((100% - 8px) / 3);
|
||||
background-color: var(--PrimaryColor);
|
||||
z-index: 1;
|
||||
border-radius: 4px;
|
||||
transition: 0.25s ease-out;
|
||||
}
|
||||
|
||||
@media (min-width: 601px) {
|
||||
.page-constructor>#part-1>#info-type>.tabs>input[id="info-type-house"]:checked~.glider {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>#info-type>.tabs>input[id="info-type-homestead"]:checked~.glider {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>#info-type>.tabs>input[id="info-type-points"]:checked~.glider {
|
||||
transform: translateX(200%);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.page-constructor>#part-1>#info-type>.tabs {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>#info-type>.tabs>.tab {
|
||||
width: calc(100% - 8px);
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>#info-type>.tabs>.glider {
|
||||
width: calc(100% - 8px);
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>#info-type>.tabs>input[id="info-type-house"]:checked~.glider {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>#info-type>.tabs>input[id="info-type-homestead"]:checked~.glider {
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>#info-type>.tabs>input[id="info-type-points"]:checked~.glider {
|
||||
transform: translateY(200%);
|
||||
}
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>form>div {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
margin: 20px 0;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>form>div>label {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
font-size: var(--FontSize1);
|
||||
font-weight: 500;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>form>div>input {
|
||||
width: calc(100% - 10px);
|
||||
min-width: 140px;
|
||||
padding: 0 5px;
|
||||
border-radius: 6px;
|
||||
height: 30px;
|
||||
background: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
font-size: var(--FontSize2);
|
||||
}
|
||||
|
||||
.page-constructor>#part-1>form>button,
|
||||
.page-constructor>#part-2>button,
|
||||
.page-constructor>#part-3>button {
|
||||
border-radius: 6px;
|
||||
background: var(--PrimaryColor);
|
||||
color: var(--PrimaryColorText);
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 400;
|
||||
margin: 20px 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.page-constructor>#part-2>.osm-info {
|
||||
padding-bottom: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.page-constructor>#part-2>.osm-info>div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.page-constructor>#part-2>.osm-info>div {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.page-constructor>#part-2>.osm-info>div>label {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
font-size: var(--FontSize1);
|
||||
font-weight: 500;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.page-constructor>#part-2>.osm-info>div>div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.page-constructor>#part-2>.osm-info>div>div>input {
|
||||
width: calc(100% - 10px);
|
||||
min-width: 140px;
|
||||
padding: 0 5px;
|
||||
border-radius: 6px;
|
||||
height: 30px;
|
||||
background: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
font-size: var(--FontSize2);
|
||||
}
|
||||
|
||||
.page-constructor>#part-2>.osm-info>div>div>a {
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.page-constructor>#part-2>.osm-info>div>div>a>svg {
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
fill: var(--ColorThemes3);
|
||||
}
|
||||
|
||||
.page-constructor>#part-2>.osm-info>span {
|
||||
font-size: var(--FontSize5);
|
||||
margin: 10px;
|
||||
color: var(--ColorThemes3);
|
||||
}
|
||||
|
||||
.page-constructor>#part-2>.osm-info>button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 30px;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
transition: 0.15s ease-in;
|
||||
color: var(--PrimaryColorText);
|
||||
background: var(--PrimaryColor);
|
||||
border-radius: 6px;
|
||||
flex-direction: row;
|
||||
z-index: 2;
|
||||
font-size: var(--FontSize3);
|
||||
}
|
||||
|
||||
.page-constructor>#part-2>.block-map {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background: var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
box-shadow: var(--shadow-l1);
|
||||
}
|
||||
|
||||
.page-constructor>#part-2>.block-map>#map {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>input {
|
||||
font-weight: 500;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
padding: 10px;
|
||||
margin: 13px;
|
||||
font-size: var(--FontSize1);
|
||||
background: var(--ColorThemes3);
|
||||
color: var(--ColorThemes0);
|
||||
border-radius: 6px;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>#house {
|
||||
display: flex;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>#house>button {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 34px;
|
||||
min-width: 34px;
|
||||
height: calc(100% - 10px);
|
||||
background: var(--PrimaryColor);
|
||||
color: var(--PrimaryColorText);
|
||||
margin: 0 10px;
|
||||
border-radius: 6px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>#house>button>svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
fill: var(--PrimaryColorText);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>#house>.entrance {
|
||||
min-height: 200px;
|
||||
border: 1px solid var(--ColorThemes3);
|
||||
border-style: dashed;
|
||||
border-radius: 6px;
|
||||
margin: 0 10px 10px 0;
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>#house>.entrance>.entrance-info>input {
|
||||
text-align: center;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 400;
|
||||
margin: 10px;
|
||||
padding: 7px;
|
||||
color: var(--ColorThemes0);
|
||||
background: var(--ColorThemes3);
|
||||
border-radius: 4px;
|
||||
width: calc(100% - 14px - 20px);
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>#house>.entrance>.entrance-info>button,
|
||||
.page-constructor>#part-3>#house>.entrance>.floor>.floor-info>button {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
background: var(--PrimaryColor);
|
||||
color: var(--PrimaryColorText);
|
||||
margin: 25px;
|
||||
border-radius: 50%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>#house>.entrance>.entrance-info>button>svg,
|
||||
.page-constructor>#part-3>#house>.entrance>.floor>.floor-info>button>svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
fill: var(--PrimaryColorText);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>#house>.entrance>.floor {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: calc(100% - 22px);
|
||||
border: 1px solid var(--ColorThemes3);
|
||||
margin: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>#house>.entrance>.floor>.floor-info>h2 {
|
||||
position: absolute;
|
||||
width: 65px;
|
||||
right: -1px;
|
||||
top: -1px;
|
||||
margin: 0;
|
||||
background: var(--ColorThemes3);
|
||||
color: var(--ColorThemes2);
|
||||
border-radius: 0 4px 0 4px;
|
||||
font-size: var(--FontSize1);
|
||||
padding: 2px 4px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>#house>.entrance>.floor>.apartment {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: var(--ColorThemes1);
|
||||
border: 2px solid var(--PrimaryColor);
|
||||
margin: 10px;
|
||||
border-radius: 4px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>#house>.entrance>.floor>.apartment>input {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
color: var(--ColorThemes3);
|
||||
background: 0;
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>#house>.entrance>.floor>.apartment>button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 0 4px 0 4px;
|
||||
background: var(--PrimaryColor);
|
||||
font-size: var(--FontSize5);
|
||||
margin: -2px;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>#house>.entrance>.floor>.apartment>button>svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
fill: var(--PrimaryColorText);
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>.info {}
|
||||
|
||||
.page-constructor>#part-3>.info>p {
|
||||
font-size: var(--FontSize2);
|
||||
color: var(--ColorThemes3);
|
||||
opacity: 0.8;
|
||||
font-style: oblique;
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>.info>button {
|
||||
border-radius: 6px;
|
||||
background: var(--ColorThemes3);
|
||||
width: fit-content;
|
||||
height: 40px;
|
||||
padding: 0 10px;
|
||||
margin-bottom: 20px;
|
||||
text-transform: uppercase;
|
||||
display: flex
|
||||
;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>.info>button>svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
fill: var(--ColorThemes0);
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.page-constructor>#part-3>.info>button>span {
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 400;
|
||||
color: var(--ColorThemes0);
|
||||
}
|
||||
Reference in New Issue
Block a user