wind-global
This commit is contained in:
parent
79848ef36f
commit
a822fb1e36
7 changed files with 130538 additions and 6 deletions
8
package-lock.json
generated
8
package-lock.json
generated
|
|
@ -9,7 +9,8 @@
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bootstrap-icons": "^1.11.3",
|
"bootstrap-icons": "^1.11.3",
|
||||||
"leaflet": "^1.9.4"
|
"leaflet": "^1.9.4",
|
||||||
|
"leaflet-velocity": "^2.1.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/adapter-auto": "^4.0.0",
|
"@sveltejs/adapter-auto": "^4.0.0",
|
||||||
|
|
@ -1075,6 +1076,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
|
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
|
||||||
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA=="
|
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/leaflet-velocity": {
|
||||||
|
"version": "2.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/leaflet-velocity/-/leaflet-velocity-2.1.4.tgz",
|
||||||
|
"integrity": "sha512-uTmSb2/Kn28S0itlmJBMy2ZRKsisWUr2wm9rtkKXjpq9Sai7tqKdTRHKfLgTOgEdWFf5Ctt2bQoB7kb50qC7eg=="
|
||||||
|
},
|
||||||
"node_modules/locate-character": {
|
"node_modules/locate-character": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bootstrap-icons": "^1.11.3",
|
"bootstrap-icons": "^1.11.3",
|
||||||
"leaflet": "^1.9.4"
|
"leaflet": "^1.9.4",
|
||||||
|
"leaflet-velocity": "^2.1.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,24 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
|
|
||||||
|
// Check if user is authenticated (using localStorage token)
|
||||||
|
let isAuthenticated = false;
|
||||||
|
|
||||||
|
// This should be reactive to changes in auth status
|
||||||
|
$: isAuthenticated = typeof window !== 'undefined' ? !!localStorage.getItem('accessToken') : false;
|
||||||
|
|
||||||
|
function handleLogout() {
|
||||||
|
// Clear authentication tokens
|
||||||
|
localStorage.removeItem('accessToken');
|
||||||
|
localStorage.removeItem('refreshToken');
|
||||||
|
|
||||||
|
// Update auth status
|
||||||
|
isAuthenticated = false;
|
||||||
|
|
||||||
|
// Redirect to login page
|
||||||
|
goto('/login');
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav class="navbar navbar-expand-lg navbar-light bg-light fixed-top custom-navbar">
|
<nav class="navbar navbar-expand-lg navbar-light bg-light fixed-top custom-navbar">
|
||||||
|
|
@ -28,9 +47,21 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="navbar-nav">
|
<ul class="navbar-nav">
|
||||||
|
{#if isAuthenticated}
|
||||||
|
<li class="nav-item">
|
||||||
|
<button
|
||||||
|
class="nav-link nav-full-height"
|
||||||
|
on:click={handleLogout}
|
||||||
|
style="cursor: pointer;"
|
||||||
|
>
|
||||||
|
Logout
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
{:else}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link nav-full-height {$page.url.pathname === '/login' ? 'active' : ''}" href="/login">Login</a>
|
<a class="nav-link nav-full-height {$page.url.pathname === '/login' ? 'active' : ''}" href="/login">Login</a>
|
||||||
</li>
|
</li>
|
||||||
|
{/if}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,13 @@
|
||||||
let error = '';
|
let error = '';
|
||||||
let isLoading = false;
|
let isLoading = false;
|
||||||
|
|
||||||
|
async function getCsrfToken() {
|
||||||
|
const response = await fetch('http://127.0.0.1:8000/api/session/', {
|
||||||
|
credentials: 'include'
|
||||||
|
});
|
||||||
|
return response.headers.get('X-CSRFToken');
|
||||||
|
}
|
||||||
|
|
||||||
async function handleLogin() {
|
async function handleLogin() {
|
||||||
if (!username || !password) {
|
if (!username || !password) {
|
||||||
error = 'Please enter both username and password';
|
error = 'Please enter both username and password';
|
||||||
|
|
@ -15,12 +22,15 @@
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
error = '';
|
error = '';
|
||||||
|
|
||||||
|
console.log("Sending request:", username, password);
|
||||||
|
|
||||||
// login request
|
// login request
|
||||||
try {
|
try {
|
||||||
const response = await fetch('http://127.0.0.1:8000/api/login', {
|
const response = await fetch('http://127.0.0.1:8000/api/login', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRFToken': await getCsrfToken(),
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
username: username,
|
username: username,
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import * as L from 'leaflet';
|
import * as L from 'leaflet';
|
||||||
import 'leaflet/dist/leaflet.css';
|
import 'leaflet/dist/leaflet.css';
|
||||||
|
import VelocityLayer from './velocity.svelte';
|
||||||
import { distHaversine } from '../lib/mathutil.ts';
|
import { distHaversine } from '../lib/mathutil.ts';
|
||||||
|
|
||||||
import { latestPredictionParsed } from '../lib/prediction.ts';
|
import { latestPredictionParsed } from '../lib/prediction.ts';
|
||||||
|
|
@ -15,6 +16,16 @@
|
||||||
let mouseLng = 0;
|
let mouseLng = 0;
|
||||||
let inputLat = '56.3576';
|
let inputLat = '56.3576';
|
||||||
let inputLng = '39.8666';
|
let inputLng = '39.8666';
|
||||||
|
let mapContainer;
|
||||||
|
let velocityOptions = {
|
||||||
|
displayValues: true,
|
||||||
|
displayOptions: {
|
||||||
|
velocityType: 'Global Wind',
|
||||||
|
position: 'bottomleft',
|
||||||
|
emptyString: 'No velocity data',
|
||||||
|
},
|
||||||
|
data: null, // здесь будут ваши данные
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* @type {null}
|
* @type {null}
|
||||||
*/
|
*/
|
||||||
|
|
@ -56,13 +67,17 @@
|
||||||
map.setView([lat, lng], map.getZoom());
|
map.setView([lat, lng], map.getZoom());
|
||||||
};
|
};
|
||||||
|
|
||||||
onMount(() => {
|
onMount(async () => {
|
||||||
map = L.map('map').setView([51.505, -0.09], 13);
|
map = L.map('map').setView([51.505, -0.09], 13);
|
||||||
|
|
||||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||||
}).addTo(map);
|
}).addTo(map);
|
||||||
|
|
||||||
|
// Загрузка данных для velocity (пример)
|
||||||
|
const response = await fetch('src/routes/testVelo.json');
|
||||||
|
velocityOptions.data = await response.json();
|
||||||
|
|
||||||
map.on('mousemove', (e) => {
|
map.on('mousemove', (e) => {
|
||||||
mouseLat = e.latlng.lat.toFixed(6);
|
mouseLat = e.latlng.lat.toFixed(6);
|
||||||
mouseLng = e.latlng.lng.toFixed(6);
|
mouseLng = e.latlng.lng.toFixed(6);
|
||||||
|
|
@ -218,6 +233,11 @@
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div bind:this={mapContainer} style="width: 100%; height: 100vh;">
|
||||||
|
{#if map}
|
||||||
|
<VelocityLayer {map} {velocityOptions} />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.map-container {
|
.map-container {
|
||||||
|
|
|
||||||
130432
src/routes/testVelo.json
Normal file
130432
src/routes/testVelo.json
Normal file
File diff suppressed because it is too large
Load diff
32
src/routes/velocity.svelte
Normal file
32
src/routes/velocity.svelte
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
<script>
|
||||||
|
import { onMount, onDestroy } from 'svelte';
|
||||||
|
import L from 'leaflet';
|
||||||
|
import 'leaflet-velocity/dist/leaflet-velocity.css';
|
||||||
|
import 'leaflet-velocity/dist/leaflet-velocity';
|
||||||
|
|
||||||
|
export let map; // принимаем карту из родительского компонента
|
||||||
|
export let velocityOptions = {}; // параметры для velocity
|
||||||
|
|
||||||
|
let velocityLayer;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (map && !velocityLayer) {
|
||||||
|
// Создаем слой velocity
|
||||||
|
velocityLayer = L.velocityLayer(velocityOptions);
|
||||||
|
|
||||||
|
// Добавляем слой на карту
|
||||||
|
velocityLayer.addTo(map);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
if (map && velocityLayer) {
|
||||||
|
map.removeLayer(velocityLayer);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Реактивность на изменение параметров
|
||||||
|
$: if (velocityLayer && velocityOptions) {
|
||||||
|
velocityLayer.setOptions(velocityOptions);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue