Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Map] add polyline support #2340

Open
wants to merge 8 commits into
base: 2.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/Map/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# CHANGELOG

## 2.22

- Add `Polyline` support

## 2.20

- Deprecate `render_map` Twig function (will be removed in 2.21). Use
Expand Down
34 changes: 27 additions & 7 deletions src/Map/assets/dist/abstract_map_controller.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ export type Point = {
lat: number;
lng: number;
};
export type MapView<Options, MarkerOptions, InfoWindowOptions, PolygonOptions> = {
export type MapView<Options, MarkerOptions, InfoWindowOptions, PolygonOptions, PolylineOptions> = {
center: Point | null;
zoom: number | null;
fitBoundsToMarkers: boolean;
markers: Array<MarkerDefinition<MarkerOptions, InfoWindowOptions>>;
polygons: Array<PolygonDefinition<PolygonOptions, InfoWindowOptions>>;
polylines: Array<PolylineDefinition<PolylineOptions, InfoWindowOptions>>;
options: Options;
};
export type MarkerDefinition<MarkerOptions, InfoWindowOptions> = {
Expand All @@ -25,6 +26,13 @@ export type PolygonDefinition<PolygonOptions, InfoWindowOptions> = {
rawOptions?: PolygonOptions;
extra: Record<string, unknown>;
};
export type PolylineDefinition<PolylineOptions, InfoWindowOptions> = {
infoWindow?: Omit<InfoWindowDefinition<InfoWindowOptions>, 'position'>;
points: Array<Point>;
title: string | null;
rawOptions?: PolylineOptions;
extra: Record<string, unknown>;
};
export type InfoWindowDefinition<InfoWindowOptions> = {
headerContent: string | null;
content: string | null;
Expand All @@ -34,16 +42,17 @@ export type InfoWindowDefinition<InfoWindowOptions> = {
rawOptions?: InfoWindowOptions;
extra: Record<string, unknown>;
};
export default abstract class<MapOptions, Map, MarkerOptions, Marker, InfoWindowOptions, InfoWindow, PolygonOptions, Polygon> extends Controller<HTMLElement> {
export default abstract class<MapOptions, Map, MarkerOptions, Marker, InfoWindowOptions, InfoWindow, PolygonOptions, Polygon, PolylineOptions, Polyline> extends Controller<HTMLElement> {
static values: {
providerOptions: ObjectConstructor;
view: ObjectConstructor;
};
viewValue: MapView<MapOptions, MarkerOptions, InfoWindowOptions, PolygonOptions>;
viewValue: MapView<MapOptions, MarkerOptions, InfoWindowOptions, PolygonOptions, PolylineOptions>;
protected map: Map;
protected markers: Array<Marker>;
protected infoWindows: Array<InfoWindow>;
protected polygons: Array<Polygon>;
protected polylines: Array<Polyline>;
connect(): void;
protected abstract doCreateMap({ center, zoom, options, }: {
center: Point | null;
Expand All @@ -52,18 +61,29 @@ export default abstract class<MapOptions, Map, MarkerOptions, Marker, InfoWindow
}): Map;
createMarker(definition: MarkerDefinition<MarkerOptions, InfoWindowOptions>): Marker;
createPolygon(definition: PolygonDefinition<PolygonOptions, InfoWindowOptions>): Polygon;
createPolyline(definition: PolylineDefinition<PolylineOptions, InfoWindowOptions>): Polyline;
protected abstract doCreateMarker(definition: MarkerDefinition<MarkerOptions, InfoWindowOptions>): Marker;
protected abstract doCreatePolygon(definition: PolygonDefinition<PolygonOptions, InfoWindowOptions>): Polygon;
protected createInfoWindow({ definition, element, }: {
definition: MarkerDefinition<MarkerOptions, InfoWindowOptions>['infoWindow'] | PolygonDefinition<PolygonOptions, InfoWindowOptions>['infoWindow'];
element: Marker | Polygon;
protected abstract doCreatePolyline(definition: PolylineDefinition<PolylineOptions, InfoWindowOptions>): Polyline;
protected abstract createInfoWindow(args: {
definition: MarkerDefinition<MarkerOptions, InfoWindowOptions>['infoWindow'];
element: Marker;
} | {
definition: PolygonDefinition<PolygonOptions, InfoWindowOptions>['infoWindow'];
element: Polygon;
} | {
definition: PolylineDefinition<PolylineOptions, InfoWindowOptions>['infoWindow'];
element: Polyline;
}): InfoWindow;
protected abstract doCreateInfoWindow({ definition, element, }: {
protected abstract doCreateInfoWindow(args: {
definition: MarkerDefinition<MarkerOptions, InfoWindowOptions>['infoWindow'];
element: Marker;
} | {
definition: PolygonDefinition<PolygonOptions, InfoWindowOptions>['infoWindow'];
element: Polygon;
} | {
definition: PolylineDefinition<PolylineOptions, InfoWindowOptions>['infoWindow'];
element: Polyline;
}): InfoWindow;
protected abstract doFitBoundsToMarkers(): void;
protected abstract dispatchEvent(name: string, payload: Record<string, unknown>): void;
Expand Down
15 changes: 13 additions & 2 deletions src/Map/assets/dist/abstract_map_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,23 @@ class default_1 extends Controller {
this.markers = [];
this.infoWindows = [];
this.polygons = [];
this.polylines = [];
}
connect() {
const { center, zoom, options, markers, polygons, fitBoundsToMarkers } = this.viewValue;
const { center, zoom, options, markers, polygons, polylines, fitBoundsToMarkers } = this.viewValue;
this.dispatchEvent('pre-connect', { options });
this.map = this.doCreateMap({ center, zoom, options });
markers.forEach((marker) => this.createMarker(marker));
polygons.forEach((polygon) => this.createPolygon(polygon));
polylines.forEach((polyline) => this.createPolyline(polyline));
if (fitBoundsToMarkers) {
this.doFitBoundsToMarkers();
}
this.dispatchEvent('connect', {
map: this.map,
markers: this.markers,
polygons: this.polygons,
polylines: this.polylines,
infoWindows: this.infoWindows,
});
}
Expand All @@ -37,7 +40,15 @@ class default_1 extends Controller {
this.polygons.push(polygon);
return polygon;
}
createInfoWindow({ definition, element, }) {
createPolyline(definition) {
this.dispatchEvent('polyline:before-create', { definition });
const polyline = this.doCreatePolyline(definition);
this.dispatchEvent('polyline:after-create', { polyline });
this.polylines.push(polyline);
return polyline;
}
createInfoWindow(args) {
const { definition, element } = args;
this.dispatchEvent('info-window:before-create', { definition, element });
const infoWindow = this.doCreateInfoWindow({ definition, element });
this.dispatchEvent('info-window:after-create', { infoWindow, element });
Expand Down
84 changes: 59 additions & 25 deletions src/Map/assets/src/abstract_map_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

export type Point = { lat: number; lng: number };

export type MapView<Options, MarkerOptions, InfoWindowOptions, PolygonOptions> = {
export type MapView<Options, MarkerOptions, InfoWindowOptions, PolygonOptions, PolylineOptions> = {
center: Point | null;
zoom: number | null;
fitBoundsToMarkers: boolean;
markers: Array<MarkerDefinition<MarkerOptions, InfoWindowOptions>>;
polygons: Array<PolygonDefinition<PolygonOptions, InfoWindowOptions>>;
polylines: Array<PolylineDefinition<PolylineOptions, InfoWindowOptions>>;
options: Options;
};

Expand Down Expand Up @@ -36,6 +37,14 @@
extra: Record<string, unknown>;
};

export type PolylineDefinition<PolylineOptions, InfoWindowOptions> = {
infoWindow?: Omit<InfoWindowDefinition<InfoWindowOptions>, 'position'>;
points: Array<Point>;
title: string | null;
rawOptions?: PolylineOptions;
extra: Record<string, unknown>;
};

export type InfoWindowDefinition<InfoWindowOptions> = {
headerContent: string | null;
content: string | null;
Expand Down Expand Up @@ -65,21 +74,24 @@
InfoWindow,
PolygonOptions,
Polygon,
PolylineOptions,
Polyline,
> extends Controller<HTMLElement> {
static values = {
providerOptions: Object,
view: Object,
};

declare viewValue: MapView<MapOptions, MarkerOptions, InfoWindowOptions, PolygonOptions>;
declare viewValue: MapView<MapOptions, MarkerOptions, InfoWindowOptions, PolygonOptions, PolylineOptions>;

protected map: Map;
protected markers: Array<Marker> = [];
protected infoWindows: Array<InfoWindow> = [];
protected polygons: Array<Polygon> = [];
protected polylines: Array<Polyline> = [];

connect() {
const { center, zoom, options, markers, polygons, fitBoundsToMarkers } = this.viewValue;
const { center, zoom, options, markers, polygons, polylines, fitBoundsToMarkers } = this.viewValue;

Check failure on line 94 in src/Map/assets/src/abstract_map_controller.ts

View workflow job for this annotation

GitHub Actions / tests-js

Unhandled error

SyntaxError: Unexpected non-whitespace character after JSON at position 853 (line 1 column 854) ❯ object ../../../../../../../../../../../node_modules/.vite/deps/@hotwired_stimulus.js:2245:25 ❯ extended.get ../../../../../../../../../../../node_modules/.vite/deps/@hotwired_stimulus.js:2113:18 ❯ extended.connect ../../../../assets/src/abstract_map_controller.ts:94:97 ❯ extended.connect src/map_controller.ts:81:14

this.dispatchEvent('pre-connect', { options });

Expand All @@ -89,6 +101,8 @@

polygons.forEach((polygon) => this.createPolygon(polygon));

polylines.forEach((polyline) => this.createPolyline(polyline));

if (fitBoundsToMarkers) {
this.doFitBoundsToMarkers();
}
Expand All @@ -97,6 +111,7 @@
map: this.map,
markers: this.markers,
polygons: this.polygons,
polylines: this.polylines,
infoWindows: this.infoWindows,
});
}
Expand Down Expand Up @@ -129,18 +144,34 @@
return polygon;
}

createPolyline(definition: PolylineDefinition<PolylineOptions, InfoWindowOptions>): Polyline {
this.dispatchEvent('polyline:before-create', { definition });
const polyline = this.doCreatePolyline(definition);
this.dispatchEvent('polyline:after-create', { polyline });
this.polylines.push(polyline);
return polyline;
}

protected abstract doCreateMarker(definition: MarkerDefinition<MarkerOptions, InfoWindowOptions>): Marker;
protected abstract doCreatePolygon(definition: PolygonDefinition<PolygonOptions, InfoWindowOptions>): Polygon;

protected createInfoWindow({
definition,
element,
}: {
definition:
| MarkerDefinition<MarkerOptions, InfoWindowOptions>['infoWindow']
| PolygonDefinition<PolygonOptions, InfoWindowOptions>['infoWindow'];
element: Marker | Polygon;
}): InfoWindow {
protected abstract doCreatePolyline(definition: PolylineDefinition<PolylineOptions, InfoWindowOptions>): Polyline;

protected abstract createInfoWindow(
args:
| {
definition: MarkerDefinition<MarkerOptions, InfoWindowOptions>['infoWindow'];
element: Marker;
}
| {
definition: PolygonDefinition<PolygonOptions, InfoWindowOptions>['infoWindow'];
element: Polygon;
}
| {
definition: PolylineDefinition<PolylineOptions, InfoWindowOptions>['infoWindow'];
element: Polyline;
}
): InfoWindow {
const { definition, element } = args;
this.dispatchEvent('info-window:before-create', { definition, element });
const infoWindow = this.doCreateInfoWindow({ definition, element });
this.dispatchEvent('info-window:after-create', { infoWindow, element });
Expand All @@ -150,18 +181,21 @@
return infoWindow;
}

protected abstract doCreateInfoWindow({
definition,
element,
}:
| {
definition: MarkerDefinition<MarkerOptions, InfoWindowOptions>['infoWindow'];
element: Marker;
}
| {
definition: PolygonDefinition<PolygonOptions, InfoWindowOptions>['infoWindow'];
element: Polygon;
}): InfoWindow;
protected abstract doCreateInfoWindow(
args:
| {
definition: MarkerDefinition<MarkerOptions, InfoWindowOptions>['infoWindow'];
element: Marker;
}
| {
definition: PolygonDefinition<PolygonOptions, InfoWindowOptions>['infoWindow'];
element: Polygon;
}
| {
definition: PolylineDefinition<PolylineOptions, InfoWindowOptions>['infoWindow'];
element: Polyline;
}
): InfoWindow;

protected abstract doFitBoundsToMarkers(): void;

Expand Down
49 changes: 48 additions & 1 deletion src/Map/assets/test/abstract_map_controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,25 @@
return polygon;
}

doCreatePolyline(definition) {
const polyline = { polyline: 'polyline', title: definition.title };

if (definition.infoWindow) {
this.createInfoWindow({ definition: definition.infoWindow, element: polyline });
}
return polyline;
}

doCreateInfoWindow({ definition, element }) {
if (element.marker) {
return { infoWindow: 'infoWindow', headerContent: definition.headerContent, marker: element.title };
}
if (element.polygon) {
return { infoWindow: 'infoWindow', headerContent: definition.headerContent, polygon: element.title };
}
if (element.polyline) {
return { infoWindow: 'infoWindow', headerContent: definition.headerContent, polyline: element.title };
}
}

doFitBoundsToMarkers() {
Expand Down Expand Up @@ -113,6 +125,32 @@
"autoClose": true
}
}
],
"polylines": [
{
"coordinates": [
{ "lat": 48.858844, "lng": 2.294351 },
{ "lat": 48.853, "lng": 2.3499 },
{ "lat": 48.8566, "lng": 2.3522 }
],
"title": "Polyline 1",
"infoWindow": null
},
{
"coordinates": [
{ "lat": 45.764043, "lng": 4.835659 },
{ "lat": 45.750000, "lng": 4.850000 },
{ "lat": 45.770000, "lng": 4.820000 }
],
"title": "Polyline 2",
"infoWindow": {
"headerContent": "<b>Polyline 2</b>",
"content": "A polyline around Lyon with some additional info.",
"position": null,
"opened": false,
"autoClose": true
}
}
]
}'>
</div>
Expand All @@ -123,7 +161,7 @@
clearDOM();
});

it('connect and create map, marker, polygon and info window', async () => {
it('connect and create map, marker, polygon, polyline and info window', async () => {
const div = getByTestId(container, 'map');
expect(div).not.toHaveClass('connected');

Expand All @@ -132,7 +170,7 @@

const controller = application.getControllerForElementAndIdentifier(div, 'map');
expect(controller.map).toEqual({ map: 'map', center: { lat: 48.8566, lng: 2.3522 }, zoom: 4, options: {} });
expect(controller.markers).toEqual([

Check failure on line 173 in src/Map/assets/test/abstract_map_controller.test.ts

View workflow job for this annotation

GitHub Actions / tests-js

test/abstract_map_controller.test.ts > AbstractMapController > connect and create map, marker, polygon, polyline and info window

AssertionError: expected [ Array(1) ] to deeply equal [ { marker: 'marker', …(1) }, …(1) ] - Expected + Received Array [ Object { "marker": "marker", "title": "Paris", }, - Object { - "marker": "marker", - "title": "Lyon", - }, ] ❯ test/abstract_map_controller.test.ts:173:36
{ marker: 'marker', title: 'Paris' },
{ marker: 'marker', title: 'Lyon' },
]);
Expand All @@ -140,6 +178,10 @@
{ polygon: 'polygon', title: 'Polygon 1' },
{ polygon: 'polygon', title: 'Polygon 2' },
]);
expect(controller.polylines).toEqual([
{ polyline: 'polyline', title: 'Polyline 1' },
{ polyline: 'polyline', title: 'Polyline 2' },
]);
expect(controller.infoWindows).toEqual([
{
headerContent: '<b>Lyon</b>',
Expand All @@ -151,6 +193,11 @@
infoWindow: 'infoWindow',
polygon: 'Polygon 2',
},
{
headerContent: '<b>Polyline 2</b>',
infoWindow: 'infoWindow',
polyline: 'Polyline 2',
},
]);
});
});
Loading
Loading