added missing source files

This commit is contained in:
AT 2022-07-13 10:26:23 +02:00
parent 809689a614
commit 6a551b47e4
3 changed files with 164 additions and 0 deletions

View File

@ -0,0 +1,53 @@
import * as React from 'react'
import { Popup as LeafletPopup} from 'react-leaflet'
import { Item, Tag } from '../../types'
import { replaceURLs } from '../../Utils/ReplaceURLs'
export interface UtopiaPopupProps {
item: Item,
tags: Tag[]
}
const Popup = (props: UtopiaPopupProps) => {
const item: Item = props.item;
const tags: Tag[] = props.tags;
return (
<LeafletPopup maxHeight={320} minWidth={275} maxWidth={275} autoPanPadding={[30, 30]}>
<b className="text-xl font-bold">{item.name}</b>
{item.start && item.end &&
<div className="flex flex-row">
<div className="basis-2/5">
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
<span className='align-middle'>{new Date(item.start).toISOString().substring(0, 10) || ""}</span>
</div>
<div className="basis-1/5 place-content-center">
<span>-</span>
</div>
<div className="basis-2/5">
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
<span className='align-middle leading-6'>{new Date(item.end).toISOString().substring(0, 10) || ""}</span>
</div>
</div>
}
<p style={{ whiteSpace: "pre-wrap" }} dangerouslySetInnerHTML={{ __html: replaceURLs(item.text) }} />
<p>
{item.tags &&
tags.map((tag: Tag) => (
<span className="" style={{ fontWeight: "bold", display: "inline-block", color: "#fff", padding: ".3rem", borderRadius: ".5rem", backgroundColor: tag.color, margin: '.2rem', fontSize: "100%" }} key={tag.id}>#{tag.name}</span>
))
}
</p>
</LeafletPopup>
)
}
export {Popup};

View File

@ -0,0 +1,92 @@
import { TileLayer, MapContainer, Marker } from "react-leaflet";
import "leaflet/dist/leaflet.css";
import * as React from "react";
import MarkerIconFactory from '../../Utils/MarkerIconFactory';
import {Popup} from "./Popup";
import { Item, Tag } from "../../types"
import "../../index.css"
import { LatLng } from "leaflet";
import MarkerClusterGroup from 'react-leaflet-cluster'
export interface MapProps {
height: string,
width: string,
center: LatLng,
zoom: number,
places?: Item[],
events?: Item[],
tags?: Tag[],
}
const UtopiaMap = (props: MapProps) => {
let center: LatLng = new LatLng(50.6, 9.5);
if (props.center) center = props.center;
let zoom: number = 10;
if (props.zoom) zoom = props.zoom;
let height: string = "400px";
if (props.height) height = props.height;
let width: string = "100vw";
if (props.width) width = props.width;
let tagMap = new Map(props.tags?.map(key => [key.id, key]));
const getTags = (item: Item) => {
let tags: Tag[] = [];
item.tags && item.tags.forEach(element => {
if (tagMap.has(element)) { tags.push(tagMap.get(element)!) };
});
return tags;
}
return (
<MapContainer style={{ height: height, width: width }} center={center} zoom={zoom} >
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
<MarkerClusterGroup showCoverageOnHover chunkedLoading maxClusterRadius={50}>
{props.places &&
props.places.map((place: Item) => {
let tags = getTags(place);
let color1 = "#666";
let color2 = "RGBA(35, 31, 32, 0.2)";
if (tags[0]) {
color1 = tags[0].color;
}
if (tags[1]) {
color2 = tags[1].color;
}
return (
<Marker icon={MarkerIconFactory('circle', color1, color2, 'circle-solid')} key={place.id} position={[place.position.coordinates[1], place.position.coordinates[0]]}>
<Popup item={place} tags={tags} />
</Marker>
)
})
}
{props.events &&
props.events.map((event: Item) => {
let tags = getTags(event);
let color1 = "#666";
let color2 = "RGBA(35, 31, 32, 0.2)";
if (tags[0]) {
color1 = tags[0].color;
}
if (tags[1]) {
color2 = tags[1].color;
}
return (
<Marker icon={MarkerIconFactory('square', color1, color2, 'calendar-days-solid')} key={event.id} position={[event.position.coordinates[1], event.position.coordinates[0]]}>
<Popup item={event} tags={tags} />
</Marker>
)
})
}
</MarkerClusterGroup>
</MapContainer>
);
}
export { UtopiaMap, Item, Tag };

19
src/Utils/ReplaceURLs.ts Normal file
View File

@ -0,0 +1,19 @@
export function replaceURLs(message: string): string {
if (!message) return "";
var urlRegex = /(^| )(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,10}(:[0-9]{1,10})?(\/.*)?$/gm;
message = message.replace(urlRegex, function (url) {
var hyperlink = url.replace(' ', '');
if (!hyperlink.match('^https?:\/\/')) {
hyperlink = 'http://' + hyperlink;
}
return '<a href="' + hyperlink + '" target="_blank" rel="noopener noreferrer">' + url + '</a>'
});
var mailRegex = /([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/gi;
message = message.replace(mailRegex, function (mail) {
return '<a href="mailto:' + mail + '">' + mail + '</a>'
});
return message;
}