From af060f85a7bc13a5bb05e453c411f5807589e6c6 Mon Sep 17 00:00:00 2001 From: Yuval Adam <_@yuv.al> Date: Mon, 23 Sep 2024 10:10:19 +0200 Subject: Move most components into new path --- geshem/app/components/Datetime.tsx | 28 ++ geshem/app/components/Geshem.tsx | 80 ++++++ geshem/app/components/Map.tsx | 99 +++++++ geshem/app/components/Slider.tsx | 45 ++++ geshem/app/components/config.tsx | 19 ++ geshem/app/globals.css | 31 +++ geshem/app/page.tsx | 99 +------ geshem/package-lock.json | 528 ++++++++++++++++++++++++++++++++++++- geshem/package.json | 16 +- src/Datetime.tsx | 28 -- src/Geshem.tsx | 80 ------ src/Map.tsx | 99 ------- src/Slider.tsx | 45 ---- src/config.tsx | 19 -- 14 files changed, 841 insertions(+), 375 deletions(-) create mode 100644 geshem/app/components/Datetime.tsx create mode 100644 geshem/app/components/Geshem.tsx create mode 100644 geshem/app/components/Map.tsx create mode 100644 geshem/app/components/Slider.tsx create mode 100644 geshem/app/components/config.tsx delete mode 100644 src/Datetime.tsx delete mode 100644 src/Geshem.tsx delete mode 100644 src/Map.tsx delete mode 100644 src/Slider.tsx delete mode 100644 src/config.tsx diff --git a/geshem/app/components/Datetime.tsx b/geshem/app/components/Datetime.tsx new file mode 100644 index 0000000..0a8fbcf --- /dev/null +++ b/geshem/app/components/Datetime.tsx @@ -0,0 +1,28 @@ +import React from "react"; +import { DateTime as LuxonDateTime } from "luxon"; + +interface DateTimeProps { + images: string[], + slider: number +} + +export function DateTime({ images, slider }: DateTimeProps) { + let datetime = null; + + if (images.length > 0) { + const ds = images[slider].substring(5, 18); + datetime = LuxonDateTime.fromFormat(ds, "yyyyMMdd/HHmm", { + zone: "utc", + }).setZone("Asia/Jerusalem"); + } + + const date = datetime ? datetime.toFormat("dd/MM/y") : ""; + const time = datetime ? datetime.toFormat("HH:mm") : ""; + + return ( +
+
{date}
+
{time}
+
+ ); +} diff --git a/geshem/app/components/Geshem.tsx b/geshem/app/components/Geshem.tsx new file mode 100644 index 0000000..50659be --- /dev/null +++ b/geshem/app/components/Geshem.tsx @@ -0,0 +1,80 @@ +"use client" + +import React, { useState, useEffect } from "react"; +// import { BrowserRouter, Route, Routes } from "react-router-dom"; + +import { Map } from "./Map"; +import { Slider } from "./Slider"; +import { DateTime } from "./Datetime"; +import { IMAGES_BASE_URL, PLAYBACK_HOURS, PLAYBACK_SLOTS } from "./config"; + +// import "./Geshem.css"; +import "rc-slider/assets/index.css"; + +// export function App() { +// return ( +// +// +// } /> +// } /> +// +// +// ); +// } + +interface GeshemProps { + date?: string +} + +export function Geshem({ date }: GeshemProps) { + const [images, setImages] = useState([]); + const [playback] = useState( + date || + new URL(window.location.toString()).searchParams.get("history") || + undefined + ); + const [slider, setSlider] = useState(playback ? PLAYBACK_SLOTS : 9); + + useEffect(() => { + const fetchImages = async () => + fetch(`${IMAGES_BASE_URL}/imgs.json`) + .then(res => res.json()) + .then(imgs => imgs["280"]) + .then(setImages); + + const buildPlayback = async () => { + const date = playback; + const hours = Array.from(Array(PLAYBACK_HOURS).keys()).map( + h => `${String(h).padStart(2, "0")}` + ); + const minutes = Array.from(Array(6).keys()).map( + m => `${String(m * 10).padStart(2, "0")}` + ); + const paths = hours.reduce( + (acc, h) => + acc.concat(minutes.map(m => `imgs/${date}/${h}${m}/280.png`)), + [] + ); + setImages(paths); + }; + + let timer: number; + if (playback) buildPlayback(); + else { + fetchImages(); + timer = window.setInterval(fetchImages, 60 * 1000); + } + + return () => { + if (timer !== undefined) clearInterval(timer); + }; + }, [playback]); + + return ( + <> + + + + + ); +} diff --git a/geshem/app/components/Map.tsx b/geshem/app/components/Map.tsx new file mode 100644 index 0000000..39f28fa --- /dev/null +++ b/geshem/app/components/Map.tsx @@ -0,0 +1,99 @@ +import React, { useState, useEffect, useRef } from "react"; +// @ts-ignore +import mapboxgl from '!mapbox-gl'; // eslint-disable-line import/no-webpack-loader-syntax + +import { + MAPBOX_ACCESS_TOKEN, + IMAGE_COORDINATES, + IMAGES_BASE_URL +} from "./config"; + +import "mapbox-gl/dist/mapbox-gl.css"; + +interface MapProps { + slider: number, + images: string[], +} + +export function Map({ slider, images }: MapProps) { + const mapContainer = useRef(null); + const map = useRef(null); + + const [lng] = useState(35); + const [lat] = useState(31.9); + const [zoom] = useState(6.3); + const [loaded, setLoaded] = useState(false); + + const prevImages = useRef(images).current; + + useEffect(() => { + if (map.current) return; + + map.current = new mapboxgl.Map({ + accessToken: MAPBOX_ACCESS_TOKEN, + container: mapContainer.current, + style: "mapbox://styles/mapbox/dark-v9", + center: [lng, lat], + zoom: zoom, + minZoom: 5, + maxZoom: 10, + hash: false, + }); + + map.current.on("style.load", () => { + setLoaded(true); + }); + }); + + useEffect(() => { + if (!loaded) return; + + // remove old layers + prevImages.forEach((img) => { + if (!images.includes(img)) { + map.current.removeLayer(`layer-${img}`); + map.current.removeSource(`source-${img}`); + } + }); + + // add new layers + images.forEach((img, i) => { + if (!prevImages.includes(img) && !map.current.getSource(`source-${img}`)) { + map.current.addSource(`source-${img}`, { + type: "image", + url: `${IMAGES_BASE_URL}/${img}`, + coordinates: IMAGE_COORDINATES + }); + map.current.addLayer({ + id: `layer-${img}`, + source: `source-${img}`, + type: "raster", + paint: { + "raster-opacity": 0, + "raster-opacity-transition": { + duration: 0 + } + } + }); + } + }); + }, [loaded, prevImages, images]); + + useEffect(() => { + if (!loaded || !images.length) return; + images[slider] && map.current.setPaintProperty(`layer-${images[slider]}`, "raster-opacity", 0.85); + return () => { + // callback will hide the previous layer with the previous slider value + map.current.setPaintProperty(`layer-${images[slider]}`, "raster-opacity", 0); + } + }, [loaded, slider, images]); + + return ( +
+
+
+ ); +} diff --git a/geshem/app/components/Slider.tsx b/geshem/app/components/Slider.tsx new file mode 100644 index 0000000..50223fc --- /dev/null +++ b/geshem/app/components/Slider.tsx @@ -0,0 +1,45 @@ +import React from "react"; +import RcSlider, { SliderProps, SliderRef } from 'rc-slider/lib/Slider'; +import { PLAYBACK_SLOTS } from "./config"; + +// use workaround from: https://github.com/react-component/slider/issues/835#issuecomment-1201805736 +const CustomSlider = RcSlider as React.ForwardRefExoticComponent & React.RefAttributes>; + +interface GeshemSliderProps { + playback?: string, + slider: number, + setSlider: React.Dispatch> +} + +export function Slider({ playback, slider, setSlider }: GeshemSliderProps) { + const handleStyle = { + height: 40, + width: 40, + border: 0, + marginTop: -10, + boxShadow: ".5px .5px 2px 1px rgba(0,0,0,.32)" + }; + + const railStyle = { + height: 20, + backgroundColor: "#3498db" + }; + + const trackStyle = { + display: "none" + }; + + return ( +
+ setSlider(val)} + /> +
+ ); +} diff --git a/geshem/app/components/config.tsx b/geshem/app/components/config.tsx new file mode 100644 index 0000000..4dc3d6a --- /dev/null +++ b/geshem/app/components/config.tsx @@ -0,0 +1,19 @@ +const hostname = window !== undefined && window.location && window.location.hostname; + +const PRODUCTION = hostname && hostname.includes("geshem"); + +export const IMAGES_BASE_URL = PRODUCTION ? "https://imgs.geshem.space" : ""; + +export const MAPBOX_ACCESS_TOKEN = + "pk.eyJ1IjoieXV2YWRtIiwiYSI6ImNpcnMxbzBuaTAwZWdoa25oczlzZmkwbHcifQ.UHtLngbKm9O8945pJm23Nw"; + +export const IMAGE_COORDINATES = [ + [31.7503896894, 34.4878044232], + [37.8574239563, 34.5078463729], + [37.7157066403, 29.4538271687], + [31.9347389087, 29.4373462909] +]; + +export const PLAYBACK_HOURS = 2; + +export const PLAYBACK_SLOTS = (PLAYBACK_HOURS * 6) - 1; \ No newline at end of file diff --git a/geshem/app/globals.css b/geshem/app/globals.css index 13d40b8..62b9a76 100644 --- a/geshem/app/globals.css +++ b/geshem/app/globals.css @@ -25,3 +25,34 @@ body { text-wrap: balance; } } + +#datetime { + position: absolute; + top: 20px; + left: 20px; + color: white; + font-family: monospace; +} + +#date { + font-size: 1.4em; +} + +#time { + font-size: 2.8em; +} + +#slider { + position: fixed; + bottom: 8vh; + width: 30vw; + margin-left: 35vw; +} + +@media only screen and (max-device-width: 812px) { + #slider { + width: 80vw; + margin-left: 8vw; + z-index: 10; + } +} \ No newline at end of file diff --git a/geshem/app/page.tsx b/geshem/app/page.tsx index 433c8aa..a44da7b 100644 --- a/geshem/app/page.tsx +++ b/geshem/app/page.tsx @@ -1,101 +1,6 @@ -import Image from "next/image"; - +import { Geshem } from "@/app/components/Geshem"; export default function Home() { return ( -
-
- Next.js logo -
    -
  1. - Get started by editing{" "} - - app/page.tsx - - . -
  2. -
  3. Save and see your changes instantly.
  4. -
- - -
- -
+ ); } diff --git a/geshem/package-lock.json b/geshem/package-lock.json index 72fc3bf..2f5907b 100644 --- a/geshem/package-lock.json +++ b/geshem/package-lock.json @@ -1,24 +1,30 @@ { "name": "geshem", - "version": "0.1.0", + "version": "7.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "geshem", - "version": "0.1.0", + "version": "7.0.0", "dependencies": { "next": "14.2.13", "react": "^18", "react-dom": "^18" }, "devDependencies": { + "@types/luxon": "^3.4.2", + "@types/mapbox-gl": "^3.4.0", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "axios": "^1.7.7", "eslint": "^8", "eslint-config-next": "14.2.13", + "luxon": "^3.5.0", + "mapbox-gl": "^3.6.0", "postcss": "^8", + "rc-slider": "^11.1.6", "tailwindcss": "^3.4.1", "typescript": "^5" } @@ -36,6 +42,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@babel/runtime": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", + "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -234,6 +253,63 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@mapbox/jsonlint-lines-primitives": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz", + "integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@mapbox/mapbox-gl-supported": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-3.0.0.tgz", + "integrity": "sha512-2XghOwu16ZwPJLOFVuIOaLbN0iKMn867evzXFyf0P22dqugezfJwLmdanAgU25ITvz1TvOfVP4jsDImlDJzcWg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@mapbox/point-geometry": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz", + "integrity": "sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@mapbox/tiny-sdf": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.0.6.tgz", + "integrity": "sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/@mapbox/unitbezier": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz", + "integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/@mapbox/vector-tile": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-1.3.1.tgz", + "integrity": "sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@mapbox/point-geometry": "~0.1.0" + } + }, + "node_modules/@mapbox/whoots-js": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz", + "integrity": "sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@next/env": { "version": "14.2.13", "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.13.tgz", @@ -483,6 +559,13 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/geojson": { + "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -490,6 +573,42 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/luxon": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.4.2.tgz", + "integrity": "sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mapbox__point-geometry": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@types/mapbox__point-geometry/-/mapbox__point-geometry-0.1.4.tgz", + "integrity": "sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mapbox__vector-tile": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/mapbox__vector-tile/-/mapbox__vector-tile-1.3.4.tgz", + "integrity": "sha512-bpd8dRn9pr6xKvuEBQup8pwQfD4VUyqO/2deGjfpe6AwC8YRlyEipvefyRJUSiCJTZuCb8Pl1ciVV5ekqJ96Bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/geojson": "*", + "@types/mapbox__point-geometry": "*", + "@types/pbf": "*" + } + }, + "node_modules/@types/mapbox-gl": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@types/mapbox-gl/-/mapbox-gl-3.4.0.tgz", + "integrity": "sha512-tbn++Mm94H1kE7W6FF0oVC9rMXHVzDDNUbS7KfBMRF8NV/8csFi+67ytKcZJ4LsrpsJ+8MC6Os6ZinEDCsrunw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, "node_modules/@types/node": { "version": "20.16.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.5.tgz", @@ -500,6 +619,13 @@ "undici-types": "~6.19.2" } }, + "node_modules/@types/pbf": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/pbf/-/pbf-3.0.5.tgz", + "integrity": "sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/prop-types": { "version": "15.7.13", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", @@ -1027,6 +1153,13 @@ "dev": true, "license": "MIT" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -1053,6 +1186,18 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/axobject-query": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", @@ -1195,6 +1340,13 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/cheap-ruler": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cheap-ruler/-/cheap-ruler-4.0.0.tgz", + "integrity": "sha512-0BJa8f4t141BYKQyn9NSQt1PguFQXMXwZiA5shfoaBYHAb2fFk2RAX+tiWMoQU+Agtzt3mdt0JtuyshAXqZ+Vw==", + "dev": true, + "license": "ISC" + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -1233,6 +1385,13 @@ "node": ">= 6" } }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "dev": true, + "license": "MIT" + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -1259,6 +1418,19 @@ "dev": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -1291,6 +1463,13 @@ "node": ">= 8" } }, + "node_modules/csscolorparser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz", + "integrity": "sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==", + "dev": true, + "license": "MIT" + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -1466,6 +1645,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -1493,6 +1682,13 @@ "node": ">=6.0.0" } }, + "node_modules/earcut": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.0.tgz", + "integrity": "sha512-41Fs7Q/PLq1SDbqjsgcY7GA42T0jvaCNGXgGtsNdvg+Yv8eIu06bxv4/PoREkZ9nMDNwnUSG9OFB9+yv8eKhDg==", + "dev": true, + "license": "ISC" + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -2230,6 +2426,13 @@ "reusify": "^1.0.4" } }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "dev": true, + "license": "MIT" + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -2295,6 +2498,27 @@ "dev": true, "license": "ISC" }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -2322,6 +2546,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2383,6 +2622,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/geojson-vt": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-4.0.2.tgz", + "integrity": "sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A==", + "dev": true, + "license": "ISC" + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -2434,6 +2680,13 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/gl-matrix": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz", + "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==", + "dev": true, + "license": "MIT" + }, "node_modules/glob": { "version": "10.3.10", "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", @@ -2555,6 +2808,13 @@ "dev": true, "license": "MIT" }, + "node_modules/grid-index": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grid-index/-/grid-index-1.1.0.tgz", + "integrity": "sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==", + "dev": true, + "license": "ISC" + }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -2643,6 +2903,27 @@ "node": ">= 0.4" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -3265,6 +3546,13 @@ "node": ">=4.0" } }, + "node_modules/kdbush": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz", + "integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==", + "dev": true, + "license": "ISC" + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -3368,6 +3656,56 @@ "dev": true, "license": "ISC" }, + "node_modules/luxon": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", + "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/mapbox-gl": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-3.6.0.tgz", + "integrity": "sha512-xjYHHIJDh6haYcKY+/9jh1eywwYfIOWCgT5Fowj4JriZexx/oOtg2S7BQDMZtpFyg9IN4VLCysmUWxY0pFNRWA==", + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "workspaces": [ + "src/style-spec", + "test/build/typings" + ], + "dependencies": { + "@mapbox/jsonlint-lines-primitives": "^2.0.2", + "@mapbox/mapbox-gl-supported": "^3.0.0", + "@mapbox/point-geometry": "^0.1.0", + "@mapbox/tiny-sdf": "^2.0.6", + "@mapbox/unitbezier": "^0.0.1", + "@mapbox/vector-tile": "^1.3.1", + "@mapbox/whoots-js": "^3.1.0", + "@types/geojson": "^7946.0.14", + "@types/mapbox__vector-tile": "^1.3.4", + "cheap-ruler": "^4.0.0", + "csscolorparser": "~1.0.3", + "earcut": "^3.0.0", + "fflate": "^0.8.1", + "geojson-vt": "^4.0.2", + "gl-matrix": "^3.4.3", + "grid-index": "^1.1.0", + "kdbush": "^4.0.2", + "murmurhash-js": "^1.0.0", + "pbf": "^3.2.1", + "potpack": "^2.0.0", + "quickselect": "^3.0.0", + "rw": "^1.3.3", + "serialize-to-js": "^3.1.2", + "supercluster": "^8.0.1", + "tinyqueue": "^3.0.0", + "tweakpane": "^4.0.4", + "vt-pbf": "^3.1.3" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3392,6 +3730,29 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3432,6 +3793,13 @@ "dev": true, "license": "MIT" }, + "node_modules/murmurhash-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz", + "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==", + "dev": true, + "license": "MIT" + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -3830,6 +4198,20 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/pbf": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.3.0.tgz", + "integrity": "sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "ieee754": "^1.1.12", + "resolve-protobuf-schema": "^2.1.0" + }, + "bin": { + "pbf": "bin/pbf" + } + }, "node_modules/picocolors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", @@ -4042,6 +4424,13 @@ "dev": true, "license": "MIT" }, + "node_modules/potpack": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/potpack/-/potpack-2.0.0.tgz", + "integrity": "sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw==", + "dev": true, + "license": "ISC" + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4064,6 +4453,20 @@ "react-is": "^16.13.1" } }, + "node_modules/protocol-buffers-schema": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", + "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true, + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -4095,6 +4498,54 @@ ], "license": "MIT" }, + "node_modules/quickselect": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz", + "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==", + "dev": true, + "license": "ISC" + }, + "node_modules/rc-slider": { + "version": "11.1.6", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-11.1.6.tgz", + "integrity": "sha512-LACAaXM0hi+4x4ErDGZLy7weIQwmBIVbIgPE+eDHiHkyzMvKjWHraCG8/B22Y/tCQUPAsP02wBhKhth7mH2PIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.36.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util": { + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.43.0.tgz", + "integrity": "sha512-AzC7KKOXFqAdIBqdGWepL9Xn7cm3vnAmjlHqUnoQaTMZYhM4VlXGLkkHHxj/BZ7Td0+SOPKB4RGPboBVKT9htw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -4172,6 +4623,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true, + "license": "MIT" + }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", @@ -4229,6 +4687,16 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/resolve-protobuf-schema": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", + "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "protocol-buffers-schema": "^3.3.1" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -4303,6 +4771,13 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/safe-array-concat": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", @@ -4362,6 +4837,16 @@ "node": ">=10" } }, + "node_modules/serialize-to-js": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/serialize-to-js/-/serialize-to-js-3.1.2.tgz", + "integrity": "sha512-owllqNuDDEimQat7EPG0tH7JjO090xKNzUtYz6X+Sk2BXDnOCilDdNLwjWeFywG9xkJul1ULvtUQa9O4pUaY0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -4748,6 +5233,16 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/supercluster": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz", + "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "kdbush": "^4.0.2" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4852,6 +5347,13 @@ "node": ">=0.8" } }, + "node_modules/tinyqueue": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-3.0.0.tgz", + "integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==", + "dev": true, + "license": "ISC" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4904,6 +5406,16 @@ "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "license": "0BSD" }, + "node_modules/tweakpane": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/tweakpane/-/tweakpane-4.0.4.tgz", + "integrity": "sha512-RkWD54zDlEbnN01wQPk0ANHGbdCvlJx/E8A1QxhTfCbX+ROWos1Ws2MnhOm39aUGMOh+36TjUwpDmLfmwTr1Fg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/cocopon" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -5061,6 +5573,18 @@ "dev": true, "license": "MIT" }, + "node_modules/vt-pbf": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/vt-pbf/-/vt-pbf-3.1.3.tgz", + "integrity": "sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@mapbox/point-geometry": "0.1.0", + "@mapbox/vector-tile": "^1.3.1", + "pbf": "^3.2.1" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/geshem/package.json b/geshem/package.json index 522284f..1133ec7 100644 --- a/geshem/package.json +++ b/geshem/package.json @@ -9,18 +9,24 @@ "lint": "next lint" }, "dependencies": { + "next": "14.2.13", "react": "^18", - "react-dom": "^18", - "next": "14.2.13" + "react-dom": "^18" }, "devDependencies": { - "typescript": "^5", + "@types/luxon": "^3.4.2", + "@types/mapbox-gl": "^3.4.0", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "axios": "^1.7.7", + "eslint": "^8", + "eslint-config-next": "14.2.13", + "luxon": "^3.5.0", + "mapbox-gl": "^3.6.0", "postcss": "^8", + "rc-slider": "^11.1.6", "tailwindcss": "^3.4.1", - "eslint": "^8", - "eslint-config-next": "14.2.13" + "typescript": "^5" } } diff --git a/src/Datetime.tsx b/src/Datetime.tsx deleted file mode 100644 index 0a8fbcf..0000000 --- a/src/Datetime.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from "react"; -import { DateTime as LuxonDateTime } from "luxon"; - -interface DateTimeProps { - images: string[], - slider: number -} - -export function DateTime({ images, slider }: DateTimeProps) { - let datetime = null; - - if (images.length > 0) { - const ds = images[slider].substring(5, 18); - datetime = LuxonDateTime.fromFormat(ds, "yyyyMMdd/HHmm", { - zone: "utc", - }).setZone("Asia/Jerusalem"); - } - - const date = datetime ? datetime.toFormat("dd/MM/y") : ""; - const time = datetime ? datetime.toFormat("HH:mm") : ""; - - return ( -
-
{date}
-
{time}
-
- ); -} diff --git a/src/Geshem.tsx b/src/Geshem.tsx deleted file mode 100644 index 6e88f19..0000000 --- a/src/Geshem.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import React, { useState, useEffect } from "react"; -import { BrowserRouter, Route, Routes } from "react-router-dom"; - -import { Map } from "./Map"; -import { Slider } from "./Slider"; -import { DateTime } from "./Datetime"; - -import { IMAGES_BASE_URL, PLAYBACK_HOURS, PLAYBACK_SLOTS } from "./config"; - -import "./Geshem.css"; -import "rc-slider/assets/index.css"; - -export function App() { - return ( - - - } /> - } /> - - - ); -} - -interface GeshemProps { - date?: string -} - - -export function Geshem({ date }: GeshemProps) { - const [images, setImages] = useState([]); - const [playback] = useState( - date || - new URL(window.location.toString()).searchParams.get("history") || - undefined - ); - const [slider, setSlider] = useState(playback ? PLAYBACK_SLOTS : 9); - - useEffect(() => { - const fetchImages = async () => - fetch(`${IMAGES_BASE_URL}/imgs.json`) - .then(res => res.json()) - .then(imgs => imgs["280"]) - .then(setImages); - - const buildPlayback = async () => { - const date = playback; - const hours = Array.from(Array(PLAYBACK_HOURS).keys()).map( - h => `${String(h).padStart(2, "0")}` - ); - const minutes = Array.from(Array(6).keys()).map( - m => `${String(m * 10).padStart(2, "0")}` - ); - const paths = hours.reduce( - (acc, h) => - acc.concat(minutes.map(m => `imgs/${date}/${h}${m}/280.png`)), - [] - ); - setImages(paths); - }; - - let timer: number; - if (playback) buildPlayback(); - else { - fetchImages(); - timer = window.setInterval(fetchImages, 60 * 1000); - } - - return () => { - if (timer !== undefined) clearInterval(timer); - }; - }, [playback]); - - return ( - <> - - - - - ); -} diff --git a/src/Map.tsx b/src/Map.tsx deleted file mode 100644 index 39f28fa..0000000 --- a/src/Map.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import React, { useState, useEffect, useRef } from "react"; -// @ts-ignore -import mapboxgl from '!mapbox-gl'; // eslint-disable-line import/no-webpack-loader-syntax - -import { - MAPBOX_ACCESS_TOKEN, - IMAGE_COORDINATES, - IMAGES_BASE_URL -} from "./config"; - -import "mapbox-gl/dist/mapbox-gl.css"; - -interface MapProps { - slider: number, - images: string[], -} - -export function Map({ slider, images }: MapProps) { - const mapContainer = useRef(null); - const map = useRef(null); - - const [lng] = useState(35); - const [lat] = useState(31.9); - const [zoom] = useState(6.3); - const [loaded, setLoaded] = useState(false); - - const prevImages = useRef(images).current; - - useEffect(() => { - if (map.current) return; - - map.current = new mapboxgl.Map({ - accessToken: MAPBOX_ACCESS_TOKEN, - container: mapContainer.current, - style: "mapbox://styles/mapbox/dark-v9", - center: [lng, lat], - zoom: zoom, - minZoom: 5, - maxZoom: 10, - hash: false, - }); - - map.current.on("style.load", () => { - setLoaded(true); - }); - }); - - useEffect(() => { - if (!loaded) return; - - // remove old layers - prevImages.forEach((img) => { - if (!images.includes(img)) { - map.current.removeLayer(`layer-${img}`); - map.current.removeSource(`source-${img}`); - } - }); - - // add new layers - images.forEach((img, i) => { - if (!prevImages.includes(img) && !map.current.getSource(`source-${img}`)) { - map.current.addSource(`source-${img}`, { - type: "image", - url: `${IMAGES_BASE_URL}/${img}`, - coordinates: IMAGE_COORDINATES - }); - map.current.addLayer({ - id: `layer-${img}`, - source: `source-${img}`, - type: "raster", - paint: { - "raster-opacity": 0, - "raster-opacity-transition": { - duration: 0 - } - } - }); - } - }); - }, [loaded, prevImages, images]); - - useEffect(() => { - if (!loaded || !images.length) return; - images[slider] && map.current.setPaintProperty(`layer-${images[slider]}`, "raster-opacity", 0.85); - return () => { - // callback will hide the previous layer with the previous slider value - map.current.setPaintProperty(`layer-${images[slider]}`, "raster-opacity", 0); - } - }, [loaded, slider, images]); - - return ( -
-
-
- ); -} diff --git a/src/Slider.tsx b/src/Slider.tsx deleted file mode 100644 index 50223fc..0000000 --- a/src/Slider.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import React from "react"; -import RcSlider, { SliderProps, SliderRef } from 'rc-slider/lib/Slider'; -import { PLAYBACK_SLOTS } from "./config"; - -// use workaround from: https://github.com/react-component/slider/issues/835#issuecomment-1201805736 -const CustomSlider = RcSlider as React.ForwardRefExoticComponent & React.RefAttributes>; - -interface GeshemSliderProps { - playback?: string, - slider: number, - setSlider: React.Dispatch> -} - -export function Slider({ playback, slider, setSlider }: GeshemSliderProps) { - const handleStyle = { - height: 40, - width: 40, - border: 0, - marginTop: -10, - boxShadow: ".5px .5px 2px 1px rgba(0,0,0,.32)" - }; - - const railStyle = { - height: 20, - backgroundColor: "#3498db" - }; - - const trackStyle = { - display: "none" - }; - - return ( -
- setSlider(val)} - /> -
- ); -} diff --git a/src/config.tsx b/src/config.tsx deleted file mode 100644 index 4ca4578..0000000 --- a/src/config.tsx +++ /dev/null @@ -1,19 +0,0 @@ -const hostname = window && window.location && window.location.hostname; - -const PRODUCTION = hostname.includes("geshem"); - -export const IMAGES_BASE_URL = PRODUCTION ? "https://imgs.geshem.space" : ""; - -export const MAPBOX_ACCESS_TOKEN = - "pk.eyJ1IjoieXV2YWRtIiwiYSI6ImNpcnMxbzBuaTAwZWdoa25oczlzZmkwbHcifQ.UHtLngbKm9O8945pJm23Nw"; - -export const IMAGE_COORDINATES = [ - [31.7503896894, 34.4878044232], - [37.8574239563, 34.5078463729], - [37.7157066403, 29.4538271687], - [31.9347389087, 29.4373462909] -]; - -export const PLAYBACK_HOURS = 2; - -export const PLAYBACK_SLOTS = (PLAYBACK_HOURS * 6) - 1; \ No newline at end of file -- cgit v1.3.1