T2857 JDD component for a map with a pin (open-source)

Summary: Ref < T2857>

Reviewers: FilipI

Reviewed By: FilipI

Subscribers: kuba-orlik, FilipI, jenkins-user

Maniphest Tasks: T2857

Differential Revision: https://hub.sealcode.org/D1375
This commit is contained in:
Kuba Orlik 2024-03-21 12:33:54 +01:00
parent 318f8df49f
commit dc8e9eefed
6 changed files with 185 additions and 1 deletions

4
public/pin-icon.svg Normal file
View File

@ -0,0 +1,4 @@
<svg width="29" height="41" viewBox="0 0 29 41" fill="none" xmlns="http://www.w3.org/2000/svg">
<ellipse cx="14.5" cy="15.4219" rx="7" ry="7.5" fill="white"/>
<path d="M28.4657 14.2917C28.0051 7.02103 21.6168 0.921875 14.4905 0.921875H14.3875C10.6918 0.953431 7.21825 2.46022 4.60475 5.1691C1.95692 7.90755 0.5 11.5404 0.5 15.3981C0.5 27.7434 13.1728 40.0827 13.7115 40.6014C13.9336 40.8154 14.2178 40.9219 14.501 40.9219C14.7841 40.9219 15.0673 40.8154 15.2885 40.6014C15.8416 40.0669 28.5 27.7414 28.5 15.4031C28.5 15.0313 28.4895 14.6615 28.4657 14.2927V14.2917ZM14.501 21.9065C11.0293 21.9065 8.2051 18.9856 8.2051 15.3952C8.2051 11.8047 11.0293 8.88381 14.501 8.88381C17.9726 8.88381 20.7949 11.8047 20.7949 15.3952C20.7949 18.9856 17.9707 21.9065 14.501 21.9065Z" fill="#CADAE4"/>
</svg>

After

Width:  |  Height:  |  Size: 794 B

View File

@ -6,5 +6,8 @@ export const registry = new Registry();
import { ImageDemo } from "./image-demo/image-demo.jdd.js"; import { ImageDemo } from "./image-demo/image-demo.jdd.js";
registry.add("image-demo", ImageDemo); registry.add("image-demo", ImageDemo);
import { MapWithPins } from "./map-with-pins/map-with-pins.jdd.js";
registry.add("map-with-pins", MapWithPins);
import { NiceBox } from "./nice-box/nice-box.jdd.js"; import { NiceBox } from "./nice-box/nice-box.jdd.js";
registry.add("nice-box", NiceBox); registry.add("nice-box", NiceBox);

View File

@ -0,0 +1,50 @@
.map-with-pins {
#map {
height: 534px;
}
.popup {
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
background: #0d4d69;
color: #ffffff;
text-align: center;
}
.leaflet-popup-content {
margin: 0;
}
.leaflet-popup-content-wrapper {
padding: 22px;
}
}
.title,
.address {
margin: 0 0 8px 0;
}
.title {
text-transform: uppercase;
font-size: 22px;
line-height: 26px;
}
.address {
font-size: 12px;
line-height: 21px;
}
.button {
display: inline-block;
margin: 0 auto;
text-align: center;
text-decoration: none;
border-radius: 25px;
text-transform: uppercase;
padding: 4px 25px;
border: 1px solid #ffffff;
color: #ffffff;
min-width: 170px;
line-height: 18px;
font-size: 12px;
background-color: #0d4d69;
}
}

View File

@ -0,0 +1,126 @@
import { FlatTemplatable, TempstreamJSX } from "tempstream";
import {
Component,
ComponentArguments,
ExtractStructuredComponentArgumentsValues,
JDDContext,
} from "@sealcode/jdd";
const coordinates = new ComponentArguments.ShortText();
coordinates.setExampleValues([
"52.39706859245613, 16.898251247012197",
"52.8, 16.6",
"52.5, 16.1",
"52.1, 16.35",
]);
const component_arguments = {
pins: new ComponentArguments.List(
new ComponentArguments.Structured({
title: new ComponentArguments.ShortText(),
address: new ComponentArguments.ShortText(),
coordinates,
button: new ComponentArguments.Structured({
text: new ComponentArguments.ShortText(),
link: new ComponentArguments.ShortText(),
}),
})
),
} as const;
export class MapWithPins extends Component<typeof component_arguments> {
getArguments() {
return component_arguments;
}
toHTML(
{ pins }: ExtractStructuredComponentArgumentsValues<typeof component_arguments>,
{ render_markdown }: JDDContext
): FlatTemplatable {
return (
<div class="map-with-pins">
<link
rel="stylesheet"
href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
crossorigin=""
/>
<script
onload="loadMap()"
src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
crossorigin=""
></script>
{
/* HTML */ `<script>
function loadMap() {
const mapDiv = document.getElementById("map");
const resizeObserver = new ResizeObserver(() => {
map.invalidateSize();
});
resizeObserver.observe(mapDiv);
var map = L.map("map");
L.tileLayer(
"https://tile.openstreetmap.org/{z}/{x}/{y}.png",
{
maxZoom: 19,
attribution:
'&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
}
).addTo(map);
const pins = ${JSON.stringify(pins)};
pins.forEach((pin) => addPin(pin, map));
}
function addPin(pin, map) {
var pinIcon = L.icon({
iconUrl: "/pin-icon.svg",
iconSize: [29, 41],
iconAnchor: [14, 40],
popupAnchor: [-3, 14],
});
var marker = L.marker(
pin.coordinates.split(", ").map((x) => parseFloat(x)),
{
icon: pinIcon,
}
).addTo(map);
var popup = L.popup({
closeButton: false,
autoClose: false,
closeOnEscapeKey: false,
closeOnClick: false,
className: "popup",
offset: [0, -32],
maxWidth: "auto",
})
.setLatLng(
pin.coordinates.split(", ").map((x) => parseFloat(x))
)
.setContent(
/* HTML */ \`<div class="popup-content">
<p class="title">\${pin.title}</p>
<p class="address">\${pin.address}</p>
<a class="button" href="\${pin.button.link}">
\${pin.button.text}
</a>
</div> \`
)
.addTo(map);
map.setView(
pin.coordinates.split(", ").map((x) => parseFloat(x)),
13
);
}
</script>`
}
<div id="map"></div>
</div>
);
}
}

View File

@ -156,7 +156,7 @@ export default new (class ComponentsPage extends StatefulPage<
wrapInLayout(ctx: BaseContext, content: Templatable): Templatable { wrapInLayout(ctx: BaseContext, content: Templatable): Templatable {
return html(ctx, "Components", content, { return html(ctx, "Components", content, {
morphing: true, morphing: false,
preserveScroll: true, preserveScroll: true,
autoRefreshCSS: true, autoRefreshCSS: true,
navbar: () => ``, navbar: () => ``,

View File

@ -2,6 +2,7 @@
@import "../node_modules/@sealcode/sealgen/src/forms/forms.css"; @import "../node_modules/@sealcode/sealgen/src/forms/forms.css";
@import "back/jdd-components/image-demo/image-demo.css"; @import "back/jdd-components/image-demo/image-demo.css";
@import "back/jdd-components/map-with-pins/map-with-pins.css";
@import "back/routes/common/ui/input.css"; @import "back/routes/common/ui/input.css";
@import "back/routes/components.css"; @import "back/routes/components.css";
@import "colors.css"; @import "colors.css";